static关键字以及Java静态变量和静态方法
static 修饰符能够与变量、方法一起使用,表示是“静态”的。静态变量和静态方法能够通过类名来访问,不需要创建一个类的对象来访问该类的静态成员,所以static修饰的成员又称作类变量和类方法。静态变量与实例变量不同,实例变量总是通过对象来访问,因为它们的值在对象和对象之间有所不同。
public class Demo {
static int i = 10;
int j;
Demo() {
this.j = 20;
}
public static void main(String[] args) {
System.out.println("类变量 i=" + Demo.i);
Demo obj = new Demo();
System.out.println("实例变量 j=" + obj.j);
}
}
运行结果:类变量 i=10 实例变量 j=20
static 的内存分配
静态变量属于类,不属于任何独立的对象,所以无需创建类的实例就可以访问静态变量。之所以会产生这样的结果,是因为编译器只为整个类创建了一个静态变量的副本,也就是只分配一个内存空间,虽然有多个实例,但这些实例共享该内存。实例变量则不同,每创建一个对象,都会分配一次内存空间。。。
public class Demo { static int i; int j; public static void main(String[] args) { Demo obj1 = new Demo(); obj1.i = 10; obj1.j = 20; Demo obj2 = new Demo(); System.out.println("obj1.i=" + obj1.i + ", obj1.j=" + obj1.j); System.out.println("obj2.i=" + obj2.i + ", obj2.j=" + obj2.j); } }
运行结果:obj1.i=10, obj1.j=20 obj2.i=10, obj2.j=0
注意:静态变量虽然也可以通过对象来访问,但是不被提倡,编译器也会产生警告。 注意:static 的变量是在类装载的时候就会被初始化。也就是说,只要类被装载,不管你是否使用了这个static 变量,它都会被初始化。小结:类变量(class variables)用关键字 static 修饰,在类加载的时候,分配类变量的内存,以后再生成类的实例对象时,将共享这块内存(类变量),任何一个对象对类变量的修改,都会影响其它对象。外部有两种访问方式:通过对象来访问或通过类名来访问。
插曲:(局部变量和成员变量主要是他们作用域的区别,成员变量个是类内部;局部变量是定义其的方法体内部(或者方法体内部的某一程序块内——大括号,主要看定义的置)。另外,成员变量可以不显式初始化,它们可以由系统设定默认值;局部变量没有默认值,所以必须设定初始赋值。还有,在内存中的位置也不一样。成员变量在所在类被实例化后,存在堆内存中;局部变量在所在方法调用时,存在栈内存空间中。)public class A{
String id; //实例变量
private String Tel; //实例变量
private int size; //实例变量
private static String depart; //类变量
final String design="样式"; //常量
}
其中实例变量、类变量、常量都是属于成员变量的,成员变量又被称为全局变量,
成员变量的范围比实例变量更宽泛
------------------------------------------------静态方法--------------------------
静态方法是一种不能向对象实施操作的方法。例如,Math 类的 pow() 方法就是一个静态方法,语法为 Math.pow(x, a),用来计算 x 的 a 次幂,在使用时无需创建任何 Math 对象。静态方法不能操作对象,所以不能在静态方法中访问实例变量,只能访问自身类的静态变量。
以下情形可以使用静态方法:
关于静态变量和静态方法的总结:
static 方法不需它所属的类的任何实例就会被调用,因此没有 this 值,不能访问实例变量,否则会引起编译错误
----------------------------------------------静态初始器(静态块)-------------------------------------------------------------------
块是由大括号包围的一段代码。静态初始器(Static Initializer)是一个存在于类中、方法外面的静态块。静态初始器仅仅在类装载的时候(第一次使用类的时候)执行一次,往往用来初始化静态变量。
public class Demo { public static int i; static{ i = 10; System.out.println("Now in static block."); } public void test() { System.out.println("test method: i=" + i); } public static void main(String[] args) { System.out.println("Demo.i=" + Demo.i); new Demo().test(); } }
导入后,可以在当前类中直接用方法名调用静态方法,不必再用 className.methodName 来访问。对于使用频繁的静态变量和静态方法,可以将其静态导入。静态导入的好处是可以简化一些操作,例如输出语句 System.out.println(); 中的 out 就是 System 类的静态变量,可以通过 import static java.lang.System.*; 将其导入,下次直接调用 out.println() 就可以了。
------------------------------------------final关键字:阻止继承和多态--------------------------------------------
final 所修饰的数据具有“终态”的特征,表示“最终的”意思。具体规定如下:
final 一般用于修饰那些通用性的功能、实现方式或取值不能随意被改变的数据,以避免被误用例如实现数学三角方法、幂运算等功能的方法,以及数学常量π=3.141593、e=2.71828 等。 如果变量被标记为 final,其结果是使它成为常数。想改变 final 变量的值会导致一个编译错误。
final 也可以用来修饰类(放在 class 关键字前面),阻止该类再派生出子类,例如 Java.lang.String 就是一个 final 类。这样做是出于安全原因,因为要保证一旦有字符串的引用,就必须是类 String 的字符串,而不是某个其它类的字符串(String 类可能被恶意继承并篡改)。
方法也可以被 final 修饰,被 final 修饰的方法不能被覆盖;变量也可以被 final 修饰,被 final 修饰的变量在创建对象以后就不允许改变它们的值了。一旦将一个类声明为 final,那么该类包含的方法也将被隐式地声明为 final,但是变量不是。
被 final 修饰的方法为静态绑定,不会产生多态(动态绑定),程序在运行时不需要再检索方法表,能够提高代码的执行效率。在Java中,被 static 或 private 修饰的方法会被隐式的声明为 final,因为动态绑定没有意义。
在Java中,数据等价的基本含义是指两个数据的值相等。在通过 equals() 和“==”进行比较的时候,引用类型数据比较的是引用,即内存地址,基本数据类型比较的是值。注意: