java中的内部类刚开始学习的时候迷惑了很久,现在终于算是有点收货了,分享出来。
要说java中的内部类,就得先说下java中的三种修饰不同对象的修饰符:
类修饰符:
public :公共类,可以被任何的对象访问,一个程序的主类必须是公共类。
abstract:抽象类,存在没有实现的方法,必须由子类实现并实例化。
final:不能被其他的类继承。
default:相同的包中使用。
成员变量修饰符:
public:可以被其他任何对象访问。
private:只可以在本类中被访问,其他任何类(包括子类)都不能访问。
protected:可以类本身和子类访问,非子类不可以访问。
default:同一个包中可以访问,其他包中不能访问。
final :最终修饰符,变量的值不可以改变。
static:修饰的变量被所有对象共享,可以直接通过类名访问。
方法修饰符:
public:
private:
protected:
default:(这四个的作用范围和局部变量的作用范围相同)
final:该方法不能被复写。
static:不需要实例化就可以调用,即直接通过类名调用。
synchronize:同步修饰符,在多线程中,该修饰符用于在运行前,对他修饰的方法加锁,以防止其他的线程访问,运行结束后解锁。
native,本地修饰符,表示此方法的方法体是其他语言在程序外部编写的。
//注:static不能修饰类内部的局部变量!!
刚开始的时候很容易混用,原因其实就是没有掌握了上面三种情况下的修饰符的使用规则。
在一般的情况下,class是只有四个修饰符的,但是当class在类内部的,即内部类的时候,会产生很多新的用法,他拥有了访问外部类内部成员属性和成员函数的权限,并且在建立对象的时候,根据不同的属性有不同的建立方法。以下是不同情况下建立对象的方法。
1 package test; 2 3 import myutil.SOP; 4 5 //测试内部类 6 public class TestInner { 7 public static void main(String[] args) { 8 // TODO Auto-generated method stub 9 new Outer1().new Inner1().func();//Outer.Inner i = new Outer().new Inner(); 10 new Outer2.Inner2().func(); 11 Outer3.Inner3.func(); 12 new Outer4().method(); 13 } 14 15 } 16 17 class Outer1{ 18 private int x = 100; 19 class Inner1{ 20 void func(){ 21 System.out.println("Inner1 ----"+Outer1.this.x); 22 } 23 } 24 } 25 class Outer2{ 26 static int x = 100; 27 static class Inner2{ 28 static int i = 200; 29 void func(){ 30 System.out.println("Inner2 ----"+x++); 31 } 32 } 33 } 34 class Outer3{ 35 static private int x = 100; 36 static final class Inner3{ 37 static void func(){ 38 System.out.println("Inner3 ----"+x); 39 } 40 } 41 } 42 43 class Outer4 { 44 int i = 200; 45 void method(){ 46 final int j =100; 47 class Inner{ 48 void show(){ 49 SOP.sop(i + " "+ j); 50 } 51 } 52 new Inner().show(); 53 } 54 }
例子分析如下:
第一种情况下:内部类为default修饰,如果要建立内部类的对象,就要先建立外部类的对象再建立内部类的对象,先用到外部类的构造函数,再用到内部类的构造函数,再访问成员函数。
第二种情况下:内部类用static修饰,如果要建立内部类的对象,因为是static和外部类同时存在的,所以,可以直接通过外部类名访问内部类,但是建立内部类的时候还要构造函数。
第三种情况下:内部类用static修饰,内部类的成员函数也用static修饰,这时候如果要调用函数就可以直接通过调用外部类的类名加内部类的类名加内部类的函数名直接调用了。
第四种情况下,内部类被定义在外部类的函数中,参考局部变量,这时候不可以被成员修饰符修饰。比如static。可以直接访问外部类中的成员,但是对于他所在函数内的局部变量,只能访问用final修饰的。
而且在内部类中,因为在一个作用域中,所以内部类可以直接访问外部类中的成员函数和成员变量。
这时候在第一种情况下,因为内部类是在外部类的实例建立后建立的,所以他访问的外部类的成员变量可以是随外部类建立而建立的。
而在第二、第三种情况下,内部类是和外部类同时出现的,所以只能访问外部类中用static修饰的变量。
最后总结如下:
内部类是外部类的成员,依附外部类存在,他可以用修饰成员变量的修饰符来修饰比如(public private protected final static)。而外部类不可以:外部类只能使用publi和default。这里有一点注意的容易混淆的是内部类和外部类的成员变量,虽然两者不同,但是却可以用相同的修饰符修饰。
内部类的访问:
1)外部类不能直接访问内部类的的成员,但可以通过内部类对象来访问。(即使内部类是static的情况下也不可以)
2)内部类作为外部类的成员,可以访问外部类的所有成员。(但是静态内部类只能访问外部类的静态成员)
3)内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。对于一个名为outer的外部类和其内部定义的名为inner的内部类。编译完成后出现outer.class和outer$inner.class两类。
在一个方法中定义的内部类
在方法中定义的内部类称为局部内部类。与局部变量类似,在局部内部类前不加修饰符public和private,其范围为定义它的代码块。其他用法和成员内部类相同。
静态内部类其实已经脱离了外部类。在创建静态内部类对象时也不需要外部类对象的存在。其实质是一个放置在别的类内部的普通类。而关键字static也只是说明其在创建对象时不依赖于外部类对象的存在,并不是说这个类本身是静态的。
静态内部类与前面所讲的两种非静态内部类的语法基本相同。区别主要是在内部类的声明前面要加上static 关键字。另外,静态内部类也不可以用private进行定义。因为用private修饰后其他类是不可能调用这个类了,而这个类也就没有存在的意义了。
静态内部类与非静态内部类的区别是本质上的。非静态内部类是外部类对象组成的一部分,主要是辅助外部类对象工作的,与外部类对象存在这对成员变量的共享关系。