一、final关键字
final可以修饰变量、方法及类:
1、当定义一个final变量时,jvm会将其分配到常量池中,其所修饰的对象只能赋值一次,对基本类型来说是其值不可变,引用类型(包括作为函数形参或类变量):引用不可以被修改该。当作为类变量时, 其初始化可以在两个地方,一是其定义处,也就是说在final变量定义时直接给其赋值,二是在构造函数中,这两个地方只能选其一。
2、当修饰一个方法时,该方法在子类中将不能被重写。
通常,如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。
使用final方法的原因有二:
第一、把方法锁定,防止任何继承类修改它的意义和实现。
第二、高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。
3、当修饰一个类时,该类不能被继承。
因此final类的成员方法没有机会被覆盖,默认都是final的。在设计类时候,如果这个类不需要有子类,类的实现细节不允许改变,并且确信这个类不会再被扩展,那么就设计为final类。
二、staic
static 用法:
1.static 可以修饰【内部类】、方法和成员变量。
2.static【不可以修饰外部类】、【不可以修饰局部变量】(因为 static 本身就是定义为类级别的,所以局部级别的变量是不可以用 static 修饰的)。
被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。static成员可以直接通过类名访问。
static变量前可以有private修饰,表示这个变量可以在类的静态代码块中,或者类的其他静态成员方法中使用(当然也可以在非静态成员方法中使用--废话),但是不能在其他类中通过类名来直接引用,这一点很重要。实际上你需要搞明白,private是访问权限限定,static表示不要实例化就可以使用
用static修饰的代码块表示静态代码块,当Java虚拟机(JVM)加载类时,就会执行该代码块。
static变量
按照是否为静态的,对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量;另一种是没有被static修饰的变量,叫实例变量。两者的区别是:
对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。对于实例变量,每创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。
static 方法
静态方法可以直接通过类名调用,任何的实例也都可以调用。因此:
- 静态方法中不能用this和super关键字;因为如果有this或super修饰,由于static方法可以使用类名直接访问,一旦使用类名直接访问,由于this关键字代表了一个函数的调用对象,这时将产生冲突;
- 不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法;
- 因为static方法独立于任何实例,因此static方法必须被实现,而且不能是抽象的abstract。
static代码块
static代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。
static与final联合使用
static final用来修饰成员变量和成员方法,可简单理解为“全局常量”!
对于变量,表示一旦给值就不可修改,并且通过类名可以访问。
对于方法,表示不可覆盖,并且可以通过类名直接访问。
三、this
this关键字指向调用对象本身。this的一种常用用法就是引用类的隐藏数据域,如下:
上图中,对于隐藏的静态变量,可以通过“类名.静态变量”的方式引用
this的另一种方法是让构造函数调用同一个类的另一个构造方法,如下:
如果一个类有多个构造方法,最好尽可能使用 this(参数列表) 实现他们。通常,无参数或参数少的构造方法可以用 this(参数列表) 调用参数多的构造方法。
注意:Java要求在构造方法中,语句 this(参数列表) 应在任何语句出现之前。
四、supper
关键字supper指调用类的父类。其用途主要有两种:
1、调用父类的构造方法,supper();或supper(parraments);
使用supper调用父类构造方法时,supper语句必须在子类构造函数的第一行,这是显示调用弗雷构造函数的唯一方式。
2、调用父类的方法
构造方法可以调用重载构造方法或他的父类的构造方法。如果他们没有被显示调用,编译器将会自动的将supper(); 作为构造方法的第一条语句。例如:
在如何情况下,构造一个实例时,将会调用沿着继承链的所有父类的构造方法。当构造一个子类对象时,子类对象在完成自己的构造任务前会首先调用它父类的构造方法。如果父类继承自其它类,那么父类构造方法会在完成他自己的构造任务前调用他自己的父类的构造方法,依次类推,这个过程沿着继承体系结构持续到最后一个构造方法被调用时为止。这就是构造链。
super和this的异同:
- super(参数):调用基类中的某一个构造函数(应该为构造函数中的第一条语句)
- this(参数):调用本类中另一种形成的构造函数(应该为构造函数中的第一条语句)
- super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参)
- this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)
- 调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。如果一个类设计为扩展的,最好提供一个无参构造方法以避免程序设计错误
- super()和this()类似,区别是,super()从子类中调用父类的构造方法,this()在同一类内调用其它方法
- super()和this()均需放在构造方法内第一行
- 尽管可以用this调用一个构造器,但却不能调用两个
- this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过
- this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块
- 从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。
五、instanceof
Java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例。一个类的实例包括本身的实例,以及所有直接或间接子类的实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。
用法:
result = object instanceof class
参数:
Result:布尔类型。
Object:必选项。任意对象表达式。
Class:必选项。任意已定义的对象类。
说明:
如果 object 是 class 的一个实例,则 instanceof 运算符返回 true。如果 object 不是指定类的一个实例,或者 object 是 null,则返回 false。
注意:instanceof左边操作元(如:object)显式声明的类型与右边操作元(如:class)必须是同种类或右边是左边父类的继承关系,否则会编译出错,提示错误:Incompatible conditional operand types object and class。
例子1,继承类之间的判断。如下:
package test2; class Person { } class Student extends Person { } class Postgraduate extends Student { } class Animal { } public class test { public static void main(String[] args) { // TODO Auto-generated method stub instanceofTest(new Student()); } public static void instanceofTest(Person p) { if (p instanceof Postgraduate) System.out.println("p是类Postgraduate的实例"); if (p instanceof Person) System.out.println("p是类Person的实例"); if (p instanceof Student) System.out.println("p是类Student的实例"); if (p instanceof Object) System.out.println("p是类Object的实例"); } }
输出结果为:
p是类Person的实例
p是类Student的实例
p是类Object的实例
例子2,接口与类之间的判断:
package test2; interface A{ } class B implements A{ } class C extends B{ } public class test { public static void main(String[] args) { // TODO Auto-generated method stub A ab=new B(); A ac=new C(); B bc=new C(); B bb=new B(); C cc=new C(); System.out.println("对象实现一个接口,用这个对象和这个接口进行instanceof判断"); System.out.println("ab instanceof A="+(ab instanceof A)); System.out.println("ac instanceof A="+(ac instanceof A)); System.out.println("bc instanceof A="+(bc instanceof A)); System.out.println("bb instanceof A="+(bb instanceof A)); System.out.println("cc instanceof A="+(cc instanceof A)); System.out.println("对象和父类进行instanceof判断"); System.out.println("ab instanceof B="+(ab instanceof B)); System.out.println("ac instanceof B="+(ac instanceof B)); System.out.println("bc instanceof B="+(bc instanceof B)); System.out.println("bb instanceof B="+(bb instanceof B)); System.out.println("cc instanceof B="+(cc instanceof B)); System.out.println("对象和他的子类进行instanceof判断"); System.out.println("ab instanceof C="+(ab instanceof C)); System.out.println("ac instanceof C="+(ac instanceof C)); System.out.println("bc instanceof C="+(bc instanceof C)); System.out.println("bb instanceof C="+(bb instanceof C)); System.out.println("cc instanceof C="+(cc instanceof C)); } }
输出结果为:
对象实现一个接口,用这个对象和这个接口进行instanceof判断 ab instanceof A=true ac instanceof A=true bc instanceof A=true bb instanceof A=true cc instanceof A=true 对象和父类进行instanceof判断 ab instanceof B=true ac instanceof B=true bc instanceof B=true bb instanceof B=true cc instanceof B=true 对象和他的子类进行instanceof判断 ab instanceof C=false ac instanceof C=true bc instanceof C=true bb instanceof C=false cc instanceof C=true