读书笔记之final与static的区别与联系

在Java中,final关键字表示它所修饰的对象是“不可改变的”,但是针对不同的对象,它们之间有些细微的差别,下面我们从基础类型、引用类型、形参、方法、类这几个方面来分别讨论它的特性。

final数据(基础类型、引用类型)

class Test{
	int i;
	public Test(int i){
		this.i = i;
	}
}

public class FinalTest {
	final int j = 1;
	final int k;
	public FinalTest(){
		k = 2;
	}
	
	public static void main(String[] args){
		FinalTest value1 = new FinalTest();
		System.out.println("value1.k:" + value1.k);
		final int value2 = 11;
		//value2 = 2; //final基础类型无法重新赋值
		System.out.println("value2:" + value2);
		final Test value3 = new Test(1);
		System.out.println("value2:" + value3.i);
		value3.i = 4;
		System.out.println("value2:" + value3.i);		
	}	
}
运行结果如下:

value1.k:2
value2:11
value2:1value2:4

对于基本类型,final使数值恒定不变;而用于对象引用,final使引用恒定不变。也就是说一旦引用被初始化指向一个对象,就无法再把它改为指向另一个对象,然而,对于其自身却是可以被修改的。

因为final域在使用前必须被初始化,所以我们必须在域的定义处或者构造器中用表达式对final赋值。

final修饰方法参数

当final修饰方法参数时,里面的参数和参数引用指向的对象。但是可以改变引用对象指向的值。


final修饰方法

当一个方法被final修饰的时候,这个方法会被锁定,任何继承类都不能修改该方法。在类中,所有的private方法都被隐式的指定为final。

“覆盖”只会在某方法是基类的接口的一部分时才会出现。即,必须能将一个对象向上转型为它的基本类型并调用相同的方法。如果一个方法为private,它就不是该类接口的一部分。


如上图所示,虽然前面三个类有继承关系,但是对于f()方法,后面对前面并没有覆盖,从黄色感叹号就能看出。

final修饰的类

被final修饰的类,是不能被继承的。所以其中的方法其实也就相当于是final的啦! 


static关键字主要有以下两个作用:

第一,为某特定数据类型或对象分配单一的存储空间,而与创建对象的个数无关。

第二,实现某个方法或属性与类而不是对象关联在一起

具体而言,在Java语言中,static主要有以下几种使用情况:变量、方法、代码块。

<1>static变量

Java提供两种类型的变量,用static修饰的静态变量和非static修饰的实例变量。静态变量会随着类加载时被完全初始化,它在内存中仅有一个,保存于静态存储区,且JVM也只会为它分配一次内存,同时所有的实例都共享静态变量,可以通过类名与对象来访问它。但是在实际的操作中比较少用对象来访问它。

而实例变量属于对象,需要在对象被创建之后才会分配空间,才能被使用,它在内存中存在多个复制,只能通过“对象.实例变量”的方式来引用。

 

<2>static方法

Java中提供了static方法和非static方法。static方法是类的方法,不需要创建对象就可以被调用,而非static方法是对象的方法,只有对象被创建出来后才可以被使用。由于在类加载的时候它就存在了,不依赖于任何实例,所以static方法必须实现,也就是说它不能是抽象方法abstract。

static方法中不能使用this和super关键字,不能调用非static方法,只能访问所属类的静态成员变量和成员方法,因为当static方法被调用时,这个类的对象可能还没被创建,即使已经被创建了,也无法确定调用哪个对象的方法。同理,static方法也不能访问非static类型的变量。

 

<3>static代码块

static代码块在类中是独立于成员变量和成员函数的代码块的。注意:这些static代码块只会被执行一次。

class Book{
	public Book(String msg){
		System.out.println(msg);
	}
}
public class Person {
	Book book1 = new Book("book1成员变量初始化!");
	static Book book2 = new Book("static成员book2成员变量初始化!");
	public Person(String msg){
		System.out.println(msg);
	}
	Book book3 = new Book("book3成员变量初始化!");
	static Book book4 = new Book("static成员book4成员变量初始化!");
	public static void funStatic(){
		System.out.println("static修饰的funStatic方法!");
	}
	public static void main(String[] args){
		Person.funStatic();
		System.out.println("******************");
		Person p1 = new Person("p1初始化!");
		System.out.println("p1:" + p1);
	}
}
运行结果如下:

static成员book2成员变量初始化!
static成员book4成员变量初始化!
static修饰的funStatic方法!
******************
book1成员变量初始化!
book3成员变量初始化!
p1初始化!
p1:Chapter7.Person@1db9742

 上面的程序及运行结果可以看到,我们没有创建对象,而是通过类去调用的类方法时,尽管该方法没有任何的类成员,还是在方法调用之前就初始化了。还可以看到初始化的顺序:static成员变量->普通成员变量->构造方法。

 当final、static一起使用的时候,我们知道,定义为static,强调只有一份;定义为final,则说明它是一个常量。所以,对于变量,如果两者同时修饰,表示一旦赋值便不能修改,并且通过类名可以访问;对于方法,若两者同时修饰,表示该方法不能被覆盖,并且可以通过类名直接访问。

参考博客:

https://www.cnblogs.com/dotgua/p/6354151.html

http://www.importnew.com/20579.html

http://blog.csdn.net/jsqfengbao/article/details/44724219



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值