您的位置:首页 > 编程语言 > Java开发

Java 关键字 static 和final 理解

2017-03-31 14:48 465 查看
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/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: