1.static关键字
1.1静态变量
传统属性所具备的特征:保存在内存中,且每个对象独享属性。
在定义一个类时,只是在描述某类事物的特征和行为,并没有产生具体的数据。只有通过new关键字创建该类的实例化对象后,系统才会为每个对象分配空间,存储各自的数据。有时候,我们希望某些特定的数据在内存中只有一份,而且能够被一个类的所有实例对象所共享。例如某个学院所有学生贡献同一个学生名称,此时安全不必在每个学生对象所占用的空间中都定义一个变量来表示学生名称,而可以在对象以外的空间定义一个表示学校名称的变量让所有对象来共享。
在一个java类中,可以使用是static关键字来修饰成员变量,该变量被称作静态变量。静态变量被所有实例共享,可以使用“类名.变量名”的形式来访问。static属性又称为类属性,保存在全局数据的内存之中,所以对象都可以进行数据区的访问。
class Student{
static String schoolName;
}
public class Test {
public static void main(String[] args) {
Student stu1=new Student();
Student.schoolName="学校";
System.out.println(stu1.schoolName);
System.out.println(Student.schoolName);
}
}
注意:static关键字只能用于修饰成员变量,不能用于修饰局部变量,负责会编译错误。
错误的代码实例:
class Student{
public void study(){
static int num=10; //非法代码,编译会出错
}
}
结论:访问static属性(类属性)应使用类名称.属性名;
所有非static属性(实例变量)必须在对象实例化后使用,而static属性(类属性)不受对象实例化控制。
在定义类时,如何选择实例变量和static变量呢?
在定义类时,99%的情况都不会考虑static属性,以非static属性(及实例对象)为主
如果需要描述共享属性的概念,或者不受对象实例化控制,使用static
1.2 static 关键字可以修饰属性、修饰方法、可以用在代码块、修饰类
修饰方法时,需注意:
注意1.静态方法和实例无关,而是和类相关,因此这导致了两个情况:
- 静态方法不能直接使用非静态数据成员或调用
- this和super两个关键字不能在静态上下文中使用(this是当前实例的引用,super是当前实例父类的引用,也是和当前实例相关的)
注意2:
- 我们曾经写的方法为了简单,都统一加上了static,但实际上一个方法具体要不要带static,都需要看情况而定。
- main方法为static方法。
小结:
class Person{
//实例变量,存放在内存中
public int age;
//实例变量
public String name;
//实例变量
public String sex;
//类变量也叫静态变量,编译时已经产生,属于类本身,并且只有一份,存放在方法区
public static int count;
//被final修饰的叫常量,也属于对象,被final修饰,后续不可更改
public final int SIZE=10;
//静态的常量,属于类本身,只有一份,被final修饰,后续不可更改
public static final int COUNT=99;
//实例成员方法
public void eat(){
//局部变量
int a=10;
System.out.println("eat()!");
}
//实例成员方法
public void sleep(){
//局部变量
int a=10;
System.out.println("sleep()!");
}
//静态成员方法
public static void staticTest(){
//不能访问非静态成员
//set="men"; //错误的
System.out.println("staticTest()!");
}
}
public class Practice {
public static void main(String[] args) {
//产生对象,实例化对象
Person1 p=new Person1();
System.out.println(p.age); //默认值为0
System.out.println(p.name); //默认值为null
//System.out.println(p.count); //会有警告
//正确的访问方式
System.out.println(Person1.count);
System.out.println(Person1.COUNT);
Person1.staticTest();
//总结:所有被static所修饰的方法或者属性,全都不依赖于对象
p.eat();
p.sleep();
}
}
结果为:
数据属性的内存布局: