Static :
static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,
被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就为static变量分配一块固定的内存地址。因此运行时可以直接指向这块固定的内存地址而无需实例化。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。
1. 静态变量:
静态变量会在类被加载时初始化且只会被初始化一次。代表不论由哪个句柄指向的堆的内存地址只有一个。所有可以由类.变量名直接引用。该类所有实例的这个变量都指向同一个地址,因此称为静态变量。
2. 静态方法:
静态方法可以直接通过类名调用,任何的实例也都可以调用,
因为静态方法代表对所有实例均一致的特性。因此静态方法中不能设计特定实例的个性。所以不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员方法),只能访问所属类的静态成员变量和成员方法。
3. 静态代码块:
独立于类成员的代码块,用static修饰。只在jvm加载类时执行一次。
扩展:单例模式的使用。
public class SingletonStudentHungry {
// 静态成员变量先初始化,且只初始化一次。因此类调用的静态变量都存在同一个内存空间。
private static SingletonStudentHungry ssh = new SingletonStudentHungry();
private String name;
private SingletonStudentHungry() {
}
public void setName(String name) {
this.name = name;
}
public static synchronized SingletonStudentHungry getSingletonStudentHungry(String name) {
ssh.setName(name);
return ssh;
}
public void printSs() {
System.out.println(this);
}
@Override
public String toString() {
return "SingletonStudent [name=" + name + "]" + "\nhashcode:" + this.hashCode();
}
public static void main(String[] args) {
SingletonStudentHungry s1 = getSingletonStudentHungry("n1");
s1.printSs();
SingletonStudentHungry s2 = getSingletonStudentHungry("n2");
// 由于指向同一个堆内存地址,因此更改响应值后,所有指向哪个内存的句柄获取的name值均改变
s1.printSs();
s2.printSs();
}
}
运行结果:
Final:
1. final类:
final类不能被继承,因此final类的成员方法没有机会被覆盖,默认都是final的。在设计类时候,如果这个类不需要有子类,类的实现细节不允许改变,并且确信这个类不会载被扩展,那么就设计为final类。
2. final方法:
如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。
使用final方法的原因有二:
第一、把方法锁定,防止任何继承类修改它的意义和实现。
第二、高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。
3. final变量:
对于基础数据类型:用final定义后,如 final int a = 10;会为a在栈空间分配值,值为10.而final定义则是句柄指向的位置不能更改。因此不能对a的值进行更改。
对于引用数据类型,即类,接口,数组。定义后,栈内存储堆的内存位置。而使用final定义后,句柄始终指向那个堆,堆内存储数据可以更改,但是句柄到堆内存的指向不能更改。
4. final 参数
当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。
public class Student {
private String name;
public Student(){}
public Student(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public void printStudent(){
System.out.println(this);
}
public void changeName(Student s1 , String newName){
s1.setName(newName);
}
public void cannotChangeName(Student s2, String newName){
s2 = new Student(newName);//由于声明的s2指向另一块内存地址,因此对传入的参数没有影响
}
@Override
public String toString() {
return "Student [name=" + name + "]"+"\n "
+ "hashcode:"+this.hashCode();
}
}
public class FinalTest {
private final int a = 10;
private final Student student = new Student("caiwuxin"+":"+Math.random());
public FinalTest(){
}
public static void main(String []args){
FinalTest f1 = new FinalTest();
f1.student.printStudent();
f1.student.changeName(f1.student, "newName");
f1.student.printStudent();
f1.student.cannotChangeName(f1.student, "annotherName");
f1.student.printStudent();
System.out.println("----------------------------------");
FinalTest f2 = new FinalTest();
f2.student.printStudent();
f2.student.changeName(f2.student, "newName");
f2.student.printStudent();
f2.student.cannotChangeName(f2.student, "annotherName");
f2.student.printStudent();
//a++;无法更改
}
}
输出结果:
参考文章:内存管理 http://liu1227787871.blog.163.com/blog/static/205363197201263103320466/