Java 关键字 static 和final 理解

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/



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值