一、static
static关键字经常以修饰变量、代码等形式和构造器、父类构造器一起出现在笔试题中,首先了解static能修饰哪些东西。
1.static变量
static变量既是在实例变量的前面加个static,一般称为静态变量。
静态变量和实例变量的区别在于给类创建实例时,静态变量是所有创建的实例所共享的,而实例变量则只属于实例本身;静态变量在类加载时就会被分配内存,而实例变量在类创建实例时才会分配内存;静态变量可以直接通过类名获取,实例则是通过实例名获取。
案例如下:
public class TestStatic{ public int count1; public static int count2; public static void main(String[] args) { TestStatic a = new TestStatic(); TestStatic b = new TestStatic(); a.count1++; b.count2++; System.out.println(a.count1 + ", " + a.count2); b.count1++; b.count2++; System.out.println(b.count1 + ", " + b.count2); } }
输出结果:
1, 1
1, 2
2.static方法
和static变量类似,同样有静态方法和实例方法,所以他们的特性基本类似。不过注意的是,虽然可以用类名调用静态方法,不过不可以使用this和super调用,而且静态方法必须被实现,以及父类的静态方法不能被子类覆盖成非静态方法和父类的非静态方法不能被子类覆盖成静态方法,不可访问实例变量和实例方法。
3.static代码块
和静态方法类似,主要用于类的初始化操作。
4.new实例时,JVM是如何操作的?
如果类没有加载过 --> 加载类,同时初始化静态的属性 --> 静态代码块 --> 分配内存空间,同时初始化非静态的属性 --> 父类构造器 --> 如果声明属性有显式赋值,则覆盖 --> 匿名代码块 --> 构造器 --> 返回内存地址
二、final
作为修饰符,final可以修饰非抽象类、非抽象成员方法和变量。
1.final类
使用final修饰类旨在让该类不可继承,防止子类错误修改父类实现细节,并且确定该类不会被继承。java.lang.String就是一个典型的final类。
2.final方法
使用final修饰方法目的是防止子类覆盖父类的方法,一般而言,private修饰的方法会隐式声明为final。
3.final变量
final变量需要在声明时或者构造器中初始化,一般和static一起使用,作为常量。final变量只能赋值一次,之后将不会再改变值。
当final修饰的时引用类型时,该引用类型虽然值不可变,但是可以修改其属性值。如下例子:
public class TestFinal { public static void main(String[] args) { final Value v = new Value(10); System.out.println("Before: " + v.value); v.value = 100; System.out.println("After: " + v.value); } } class Value{ int value; public Value(int value){ this.value = value; } }
输出结果为:
Before: 10
After: 100
三、abstract
1.abstract类
抽象类不能被实例化;抽象类可以没有抽象方法,但是有抽象方法必须定义为抽象类;没有抽象构造器,没有抽象静态方法。
2.abstract方法
抽象方法用来描述要实现什么功能,但不具体实现。
四、接口
- 接口和类类似,都可以拥有属性和方法,不过方法隐式为抽象方法,没有方法体。
- 接口主要用来描述类要实现什么功能,是类的蓝图。
- 是解决类的多重继承,是极致的抽象类,只有抽象方法和属性的抽象类。
五、内部类
内部类可以分为成员内部类、局部内部类、匿名内部类和静态内部类等。
1.成员内部类
定义在类内部,方法外面,类似于类的成员,拥有四种权限,protected、public、private和default。
如下所示:
public class TestInnerClass { public static void main(String[] args) { Outter outter = new Outter(); Outter.Inner inner1 = outter.new Inner(); Outter.Inner inner2 = outter.getInner(); } } //外部类 class Outter{ private Inner inner = null; public Outter(){ } public Inner getInner(){ if(inner == null){ inner = new Inner(); } return inner; } //内部类 class Inner{ public Inner(){ } } }
2.局部内部类
局部内部类存在于方法内或者作用域中,该作用域可以是判断语句、循环等语句。类似于局部变量,相应的访问权限就在方法或者作用域中。
如下所示:
public class TestLocalInnerClass { public void run(){ class Man{ String name = "liuxiang"; } Man man = new Man(); System.out.println(man.name + " is running..."); } public static void main(String[] args) { TestLocalInnerClass localInnerClass = new TestLocalInnerClass(); localInnerClass.run(); } }
3.匿名内部类
匿名内部类一般写在方法中较多,如果要访问当前方法的局部变量,则需要使用final修饰,并且匿名内部类没有构造器。
4.静态内部类
静态内部类不可访问非静态方法和属性,不依赖外部类的对象,如果访问外部类的非静态属性和方法需要通过外部类的实例来访问。静态内部类就是在内部类的基础上加个静态,和静态方法类似,可以直接使用类名调用。