java final static
来源:互联网 发布:软件注册码怎么破 编辑:程序博客网 时间:2024/05/29 15:47
___________________________final概述____________________________
final的作用随着所修饰的类型而不同
1、final修饰类中的属性或者变量
无论属性是基本类型还是引用类型,final所起的作用都是变量里面存放的“值”不能变。
这个值,对于基本类型来说,变量里面放的就是实实在在的值,如1,“abc”等。
而引用类型变量里面放的是个地址,所以用final修饰引用类型变量指的是它里面的地址不能变,并不是说这个地址所指向的对象或数组的内容不可以变,这个一定要注意。
例如:类中有一个属性是final Person p=new Person("name"); 那么你不能对p进行重新赋值,但是可以改变p里面属性的值,p.setName('newName');
final修饰属性,声明变量时可以不赋值,而且一旦赋值就不能被修改了。对final属性可以在三个地方赋值:声明时、初始化块中、构造方法中。总之一定要赋值。
2、final修饰类中的方法
作用:可以被继承,但继承后不能被重写。
3、final修饰类
作用:类不可以被继承。
思考一个有趣的现象:
byte b1=1;
byte b2=3;
byte b3=b1+b2;//当程序执行到这一行的时候会出错,因为b1、b2可以自动转换成int类型的变量,运算时java虚拟机对它进行了转换,结果导致把一个int赋值给byte-----出错
如果对b1 b2加上final就不会出错
final byte b1=1;
final byte b2=3;
byte b3=b1+b2;//不会出错,相信你看了上面的解释就知道原因了。
4、final参数
对于基本类型的变量,这样做并没有实际意义,因为基本类型的变量在调用方法时时传值的,也就是说,你可以在方法中更改这个参数变量而不会影响调用语句,然而对于对象变量,却显得很实用,因为在对象变量在传递时是传递其引用,这样,你在方法中对对象的修改也会影响调用语句中的对象变量。当你在方法中不需要改变作为参数的对象变量时,明确地使用final进行声明,会防止你无意地修改而影响到调用方法。
_______________________static概述___________________________
被static修饰的内容可以理解为全局的,与实例无关。
能被static修饰的有成员变量(用final修饰和常量)、代码块、方法、内部类
1、简单说明类和实例的关系
可以理解为“人”和“张三”之间的关系,一个是概念信息,一个是实实在在的人
1.1、类装载器加载class文件后的结果为class对象,称之为类,属于抽象的概念模型,记录了class对象的成员变量信息、方法信息等,整个jvm中有且只有一份,存储于jvm方法区,俗称永久代
1.2、而对象实例是通过new、反射等手段将class对象实例化的结果,实例化一次便有一个实例产生,存储于jvm堆内存中
2、static修饰成员变量
2.1、静态成员变量跟类关联,与实例无关,使用类名.进行引用;内存中只有一份数据,在类加载时初始化完成,存储于永久代中,被所有实例共享;使用final关键字修饰后将不可修改,将变成静态常量
2.2、非静态成员变量在对象实例化时完成初始化,N个实例就有N份非静态成员变量数据,与实例一起被存储在堆中
2.3、使用场景
定义一些配置信息在配置文件中,系统启动后加载到静态成员变量或常量中,这样不依赖具体的对象就可以使用这些信息了
JDK代码中也有很多应用,比如数字最大最小值,Math.PI等等这些常量
3、static修饰代码块
3.1、只会在类加载时执行一次
3.2、被static修饰的代码块中不能访问非静态变量、this、super,原因是静态代码块与实例无关,所以根本就拿不到当前对象
3.3、代码块信息是类加载时被存储到jvm方法区中,不涉及内存分配问题,有多少实例也仅有一份拷贝
3.4、使用场景:一般用于初始化一些资源、2.3中提到的加载配置文件到静态成员变量,等到类加载完成后这些资源和变量就可以使用了
4、static修饰方法
4.1、静态方法跟类关联,与实例无关,使用类名.进行调用
4.2、同3.2、3.3
4.3、使用场景:工具方法,如jdk自带的Math类和apache的StringUtils类
5、static修饰内部类
5.1、static内部类,它可以不依赖于外部类实例被实例化。
5.2、static内部类的对象不能访问其外围类的对象。
5.3、不能从嵌套static内部类对象中访问非静态的外围类对象。
5.4、普通的内部类需要在外部类实例化后才能实例化。普通的内部类对象隐含地保存了一个引用,指向创建它的外围类对象。然而,当内部类是static的时,就不是这样了。
5.5、使用场景很少,不过还是有的,可参考HashMap和Entry
根据程序上下文环境,Java关键字final有“这是无法改变的”或者“终态的”含义,它可以修饰非抽象类、非抽象类成员方法和变量。你可能出于两种理解而需要阻止改变:设计或效率。
final方法不能被子类的方法覆盖,但可以被继承。
final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
final不能用于修饰构造方法。
注意:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。
final类不能被继承,因此final类的成员方法没有机会被覆盖,默认都是final的。在设计类时候,如果这个类不需要有子类,类的实现细节不允许改变,并且确信这个类不会载被扩展,那么就设计为final类。
如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。
使用final方法的原因有二:
第一、把方法锁定,防止任何继承类修改它的意义和实现。
第二、高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。(允许编译器将所有对此方法的调用转化为行内(inline)调用机制,它会在调用final方法时,直接将方法主体插入到方法调用处,而不是进行例行的方法调用,例如,保存断点,压栈等,这样可能使程序效率有所提高。然而当方法主体非常庞大时,或在多处调用此方法时,调用方法主体代码会迅速膨胀看,可能反而会影响效率,所以要慎用final进行方法定义。)
例如:
public static void main(String[] args) {
// TODO 自动生成方法存根
}
public void f1() {
System.out.println("f1");
}
//无法被子类覆盖的方法
public final void f2() {
System.out.println("f2");
}
public void f3() {
System.out.println("f3");
}
private void f4() {
System.out.println("f4");
}
}
public class Test2 extends Test1 {
public void f1(){
System.out.println("Test1父类方法f1被覆盖!");
}
public static void main(String[] args) {
Test2 t=new Test2();
t.f1();
t.f2(); //调用从父类继承过来的final方法
t.f3(); //调用从父类继承过来的方法
//t.f4(); //调用失败,无法从父类继承获得
}
}
用final修饰的成员变量表示常量,值一旦给定就无法改变!
final修饰的变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。
从下面的例子中可以看出,一旦给final变量初值后,值就不能再改变了。
另外,final变量定义的时候,可以先声明,而不给初值,这中变量也称为final空白,无论什么情况,编译器都确保空白final在使用之前必须被初始化。但是,final空白在final关键字final的使用上提供了更大的灵活性,为此,一个类中的final数据成员就可以实现依对象而有所不同,却有保持其恒定不变的特征。
public class Test3 {
private final String S = "final实例变量S";
private final int A = 100;
public final int B = 90;
public static final int C = 80;
private static final int D = 70;
public final int E; //final空白,必须在初始化对象的时候赋初值
public Test3(int x) {
E = x;
}
/**
* @param args
*/
public static void main(String[] args) {
Test3 t = new Test3(2);
//t.A=101; //出错,final变量的值一旦给定就无法改变
//t.B=91; //出错,final变量的值一旦给定就无法改变
//t.C=81; //出错,final变量的值一旦给定就无法改变
//t.D=71; //出错,final变量的值一旦给定就无法改变
System.out.println(t.A);
System.out.println(t.B);
System.out.println(t.C); //不推荐用对象方式访问静态字段
System.out.println(t.D); //不推荐用对象方式访问静态字段
System.out.println(Test3.C);
System.out.println(Test3.D);
//System.out.println(Test3.E); //出错,因为E为final空白,依据不同对象值有所不同.
System.out.println(t.E);
Test3 t1 = new Test3(3);
System.out.println(t1.E); //final空白变量E依据对象的不同而不同
}
private void test() {
System.out.println(new Test3(1).A);
System.out.println(Test3.C);
System.out.println(Test3.D);
}
public void test2() {
final int a; //final空白,在需要的时候才赋值
final int b = 4; //局部常量--final用于局部变量的情形
final int c; //final空白,一直没有给赋值.
a = 3;
//a=4; 出错,已经给赋过值了.
//b=2; 出错,已经给赋过值了.
}
}
当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。对于基本类型的变量,这样做并没有实际意义,因为基本类型的变量在调用方法时时传值的,也就是说,你可以在方法中更改这个参数变量而不会影响调用语句,然而对于对象变量,却显得很实用,因为在对象变量在传递时是传递其引用,这样,你在方法中对对象的修改也会影响调用语句中的对象变量。当你在方法中不需要改变作为参数的对象变量时,明确地使用final进行声明,会防止你无意地修改而影响到调用方法。
public static void main(String[] args) {
new Test4().f1(2);
}
public void f1(final int i) {
//i++; //i是final类型的,值不允许改变的.
System.out.print(i);
}
}
二、static
static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念。
被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。
用public修饰的static成员变量和成员方法本质是全局变量和全局方法,当声明它类的对象市,不生成static变量的副本,而是类的所有实例共享同一个static变量。
类名.静态方法名(参数列表...)
类名.静态变量名
按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量;另一种是没有被static修饰的变量,叫实例变量。两者的区别是:
对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。
对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。
静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。因为实例成员与特定的对象关联!这个需要去理解,想明白其中的道理,不是记忆!!!
因为static方法独立于任何实例,因此static方法必须被实现,而不能是抽象的abstract。
static代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。例如:
private static int a;
private int b;
static {
Test5.a = 3;
System.out.println(a);
Test5 t = new Test5();
t.f();
t.b = 1000;
System.out.println(t.b);
}
static {
Test5.a = 4;
System.out.println(a);
}
public static void main(String[] args) {
// TODO 自动生成方法存根
}
static {
Test5.a = 5;
System.out.println(a);
}
public void f() {
System.out.println("hhahhahah");
}
}
3
hhahhahah
1000
4
5
static final用来修饰成员变量和成员方法,可简单理解为“全局常量”!
对于变量,表示一旦给值就不可修改,并且通过类名可以访问。
对于方法,表示不可覆盖,并且可以通过类名直接访问。
private static final String strStaticFinalVar = "aaa";
private static String strStaticVar = null;
private final String strFinalVar = null;
private static final int intStaticFinalVar = 0;
private static final Integer integerStaticFinalVar = new Integer(8);
private static final ArrayList<String> alStaticFinalVar = new ArrayList<String>();
private void test() {
System.out.println("-------------值处理前----------\r\n");
System.out.println("strStaticFinalVar=" + strStaticFinalVar + "\r\n");
System.out.println("strStaticVar=" + strStaticVar + "\r\n");
System.out.println("strFinalVar=" + strFinalVar + "\r\n");
System.out.println("intStaticFinalVar=" + intStaticFinalVar + "\r\n");
System.out.println("integerStaticFinalVar=" + integerStaticFinalVar + "\r\n");
System.out.println("alStaticFinalVar=" + alStaticFinalVar + "\r\n");
//strStaticFinalVar="哈哈哈哈"; //错误,final表示终态,不可以改变变量本身.
strStaticVar = "哈哈哈哈"; //正确,static表示类变量,值可以改变.
//strFinalVar="呵呵呵呵"; //错误, final表示终态,在定义的时候就要初值(哪怕给个null),一旦给定后就不可再更改。
//intStaticFinalVar=2; //错误, final表示终态,在定义的时候就要初值(哪怕给个null),一旦给定后就不可再更改。
//integerStaticFinalVar=new Integer(8); //错误, final表示终态,在定义的时候就要初值(哪怕给个null),一旦给定后就不可再更改。
alStaticFinalVar.add("aaa"); //正确,容器变量本身没有变化,但存放内容发生了变化。这个规则是非常常用的,有很多用途。
alStaticFinalVar.add("bbb"); //正确,容器变量本身没有变化,但存放内容发生了变化。这个规则是非常常用的,有很多用途。
System.out.println("-------------值处理后----------\r\n");
System.out.println("strStaticFinalVar=" + strStaticFinalVar + "\r\n");
System.out.println("strStaticVar=" + strStaticVar + "\r\n");
System.out.println("strFinalVar=" + strFinalVar + "\r\n");
System.out.println("intStaticFinalVar=" + intStaticFinalVar + "\r\n");
System.out.println("integerStaticFinalVar=" + integerStaticFinalVar + "\r\n");
System.out.println("alStaticFinalVar=" + alStaticFinalVar + "\r\n");
}
public static void main(String args[]) {
new TestStaticFinal().test();
}
}
Process finished with exit code 0
看了上面这个例子,就清楚很多了,但必须明白:通过static final修饰的容器类型变量中所“装”的对象是可改变的。这是和一般基本类型和类类型变量差别很大的地方。
转载自:http://lavasoft.blog.51cto.com/62575/18771/
http://blog.csdn.net/linchunhua/article/details/5305452
参考:
Java中static的作用:http://home.cnblogs.com/group/topic/38753.html
static详解:http://blog.csdn.net/anmei2010/article/details/4096131
- java static,final,static final
- 【Java】static\final\static final区别
- java-static、final、static final的区别
- JAVA final static
- JAVA static & final
- java static final
- java static final 初始化
- Java关键字final、static
- java final 、 static 总结
- java - static - final
- Java Final static 关键字
- java关键字final、static
- JAVA-static, final
- java final、static、
- java static final 初始化
- Java static与final
- java final static
- final static public---Java
- 博弈--ZOJ 3084 S-Nim(SG)
- 递归转化为非递归的一般方法
- C++ STL 学习体会
- 如何学习运营,如何思考运营
- C# 首个程序
- java final static
- Modules的概念及使用
- 玩转STM32F0 Value Line Discovery 之 点亮LED
- DLL编程基础
- ubuntu下的c语言的第一天
- Array和ArrayList的异同点
- Makefile经典教程(掌握这些足够)
- uva 11995 I Can Guess the Data Structure!(数据结构:基础)
- NandFlash简介