static
是一个用于声明程序结构的关键字,意为“静态的”,此关键字可以用于全局属性和全局方法,主要特点是可以避免对象实例化的限制,在没有实例化对象的时候直接进行此类结构的访问。
在一个类中,主要的组成就是属性和方法,而每一个对象都分别拥有各自的属性内容(不同对象的属性保存在堆内存的不同地址中)。
如果想要类中的某个属性定义为公共属性(所有对象都可以使用的属性),则可以在声明属性前加上static
关键字。
package edu.blog.test21.staticTest01;
class Chinese {
//普通成员属性
private String name;
private int age;
//静态成员属性
static String country = "中华人民共和国";
public Chinese(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getInfo() {
return "姓名:" + this.name + "、年龄:" + this.age + "、国家:" + this.country;
}
}
public class TestDemo {
public static void main(String[] args) {
Chinese perA = new Chinese("lisi", 10);
Chinese perB = new Chinese("wangwu", 10);
System.out.println(perA.getInfo());
System.out.println(perB.getInfo());
perA.country = "伟大的中华人民共和国";
System.out.println("--------------------------");
System.out.println(perA.getInfo());
System.out.println(perB.getInfo());
}
}
/*
执行结果:
姓名:lisi、年龄:10、国家:中华人民共和国
姓名:wangwu、年龄:10、国家:中华人民共和国
--------------------------
姓名:lisi、年龄:10、国家:伟大的中华人民共和国
姓名:wangwu、年龄:10、国家:伟大的中华人民共和国
*/
本程序在Chinese
类中定义了一个static
类型的country
属性,这样该属性就成为公共属性,该属性会保存在全局数据区中,所有的对象都可以获取到相同的对象内容,当有一个对象修改了static
属性内容都会影响到此类的所有实例化对象,内存关系如下所示。
若country没有定义成static类型时,则每个实例化对象都会拥有此属性。
static描述的是全局属性,对于全局属性除了可以利用实例化对象调用外,最大的特点在于可以直接利用类名且没有实例化对象产生的情况下进行调用。
public class TestDemo {
public static void main(String[] args) {
System.out.println("直接访问static属性:" + Chinese.country);
Chinese.country = "中国";
Chinese chinese = new Chinese("lisi", 10);
System.out.println(chinese.getInfo());
}
}
/*
执行结果:
直接访问static属性:中华人民共和国
姓名:lisi、年龄:10、国家:中国
*/
小结:
static
定义的属性不在堆中保存,而是保存在全局数据区;static
定义的属性内容表示类属性,类属性可以由类名称直接调用(虽然可以通过实例化对象调用,但是并不提倡此类格式);static
属性虽然定义在类中,但是其可以在没有实例化对象的时候进行调用(普通属性保存在堆内存中,static属性保存在全局数据区中)。在编写程序代码过程中,首要选择还是普通属性,而是否需要用static
定义静态属性则根据实际需求选择。
static
除了可以进行属性定义之外,也可以进行方法的定义,其效果同static
定义成员属性类似,即都可以在没有实例化对象时通过类名直接调用,不再赘述。
接下来我们来说一说static
关键字修饰的方法和属性的访问特点:
总结成一句话就是:静态成员方法只能访问静态成员。
代码块是在程序中使用“{}”
定义起来的一段程序,而根据代码块声明位置以及声明关键字的不同,代码块可以分为:
普通代码块是定义在方法中的代码块,利用这类代码块可以解决代码在一个方法中过长导致出现重复变量定义的问题。
我们先来看一下一个例子。
package edu.blog.test21;
public class CodeBlockTestDemo01 {
public static void main(String[] args) {
if (true) {
int x = 10;
System.out.println("x:" + x);
}
int x = 100;
System.out.println("x:" + x);
}
}
/*
执行结果:
x:10
x:100
*/
我们在if语句中定义了一个变量x
,由于“{}”
的作用,所以该变量不会与外部的变量x
产生影响。
如果我们将if
语句删去,“{}”
就成了一个普通代码块,这样也可以保证两个x
变量不会相互影响,也就是说使用普通代码块可以将一个方法中的代码进行部分分割。
范例:定义普通代码块
package edu.blog.test21.block;
public class CodeBlockTestDemo02 {
public static void main(String[] args) {
{
int x = 10;
System.out.println("x:" + x);
}
int x = 100;
System.out.println("x:" + x);
}
}
/*
执行结果:
x:10
x:100
*/
将代码块定义在一个类中,这样就成为构造代码块,其主要的特点是在使用关键字new
实例化对象进行调用。
范例:定义构造代码块
package edu.blog.test21.block;
class Person {
public Person() {
System.out.println("[构造器]Person类的构造器执行");
}
{
System.out.println("[构造块]Person构造块执行");
}
}
public class CodeBlockTestDemo03 {
public static void main(String[] args) {
new Person();
System.out.println("-------------------------");
new Person();
}
}
/*
执行结果:
[构造块]Person构造块执行
[构造器]Person类的构造器执行
-------------------------
[构造块]Person构造块执行
[构造器]Person类的构造器执行
*/
通过程序的执行的结果我们发现,每一个实例化新的对象时都会调用构造块,并且构造快代码的执行优先于构造器的执行。
静态代码块也是在类中定义的,如果一个构造代码块使用了static关键字进行定义的话,那么就表示静态代码块。
静态代码块又两种情况:
范例:在非主类中定义的静态代码块
package edu.blog.test21.block;
class Person {
public Person() {
System.out.println("[构造器]Person类的构造器执行");
}
{
System.out.println("[构造块]Person构造块执行");
}
static {
System.out.println("[静态块]Person静态块执行");
}
}
public class CodeBlockTestDemo03 {
public static void main(String[] args) {
new Person();
System.out.println("-------------------------");
new Person();
}
}
/*
执行结果:
[静态块]Person静态块执行
[构造块]Person构造块执行
[构造器]Person类的构造器执行
-------------------------
[构造块]Person构造块执行
[构造器]Person类的构造器执行
*/
在本程序中实例化了多个Person
类对象,可以发现静态代码块优先于构造代码块执行,并且不管实例化多少个对象,静态代码块中的代码只执行一次。
Tips:利用静态代码块可以实现一些公共的初始化操作。
范例:在主类中定义的静态代码块
package edu.blog.test21.block;
class Person {
public Person() {
System.out.println("[构造器]Person类的构造器执行");
}
{
System.out.println("[构造块]Person构造块执行");
}
static {
System.out.println("[静态块]Person静态块执行");
}
}
public class CodeBlockTestDemo03 {
static {
System.out.println("[静态块]主类中的静态块执行了");
System.out.println("-------------------------");
}
public static void main(String[] args) {
new Person();
System.out.println("-------------------------");
new Person();
}
}
/*
执行结果:
[静态块]主类中的静态块执行了
-------------------------
[静态块]Person静态块执行
[构造块]Person构造块执行
[构造器]Person类的构造器执行
-------------------------
[构造块]Person构造块执行
[构造器]Person类的构造器执行
*/
通过程序的执行结果发现,主类中定义的静态代码块代码会优先于主方法执行。
注:此文章为个人学习笔记,若有错误,敬请指正。