java内部类

内部类在字面意思上理解就是包含在一个类里面的类。Java的官方解释为:内部类是定义在另一个类中的类。

 

一、为什么要引入内部类?

  引入内部类的原因有以下三点:

  1. 内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据。(也就是内部类中可以访问外部类的私有成员)
  2. 内部类可以对同一包的其他类隐藏起来
  3. 当想要定义一个回调函数且不想编写大量的代码的时候,使用匿名内部类比较的便捷。(如时间响应机制,线程)

  注意:内部类一般使用在只要一次调用的地方,还有对某些接口和抽象类的实现时,不想创建接口或者抽象类的具体子类的时候,可以使用抽象类,接口和抽象类的内部类的应用返回的是接口和抽象类的子类对象。

  如下代码:

Runnable runnable = new Runnable() {
@Override
public void run() {
//线程中使用匿名内部类。runnable接受的是Runnable接口的子 类对象
}
};

 

二、内部类

通过代码来分析内部类:

OuterClass类:                                                             

public class OuterClass {
  private String str1 = "private: 我是外部类的私有成员变量";
  public String str2 = "public: 我是外部类的公有成员变量";
  static String str3 = "static: 我是外部类的静态成员变量";
  public void outerTest1() {
    System.out.println("我是外部类的公有成员方法");
  }

  private void outerTest2() {
    System.out.println("我是外部类的私有成员方法");
  }

  static void outerTest3() {
    System.out.println("我是外部类的公有成员方法");
  }

  // 在外部类调用内部类的方法和变量
  public void test() {
    // 外部类不能直接访问内部类的东西,需要创建对象访问
    InnerClass inner = new InnerClass();
    System.out.println(inner.string1);
    System.out.println(inner.string2);
    inner.innerTest3();
    inner.innerTest4();
  }

  class InnerClass{
    private String string1 = "private:我是内部类私有成员变量";
    public String string2 = "public:我是内部类的公有成员变量";
    public void innerTest3() {
    System.out.println("我是内部类的公有成员方法");
  }

  private void innerTest4() {
    System.out.println("我是内部类的私有成员方法");
  }

  // 在内部类中调用外部类的成员变量
  public void innerTest1() {
    System.out.println(str1);
    System.out.println(OuterClass.this.str2);
    System.out.println(str3);
    System.out.println(str4);
  }

// 在内部类中调用外部类的成员方法
  public void innerTest2() {
    func();
    outerTest1();
    OuterClass.this.outerTest2();
    OuterClass.outerTest3();
  }
  public void show(){
    System.out.println("外围类访问外部类的内部类!!!");
  }
  }
  public String str4 = "public: 定义在内部类后边的外部类变量";
  public void func(){
    System.out.println("定义在内部类的后面的外部类方法");
  }
}


OuterInnerDemo类:                                                           
public class OuterInnerDemo {
  public static void main(String[] args) {
    OuterClass outer = new OuterClass();
    System.out.println("外部类调用内部类的成员变量及方法: ");
    outer.test();
    System.out.println();
    System.out.println("内部类调用外部类: ");
    // 创建内部类对象的方式1
    OuterClass.InnerClass inner = new OuterClass().new InnerClass();
    inner.innerTest1();
    inner.innerTest2();
    System.out.println();
    System.out.println("外围类调用内部类方法: ");
    // 创建内部类对象的方式2
    OuterClass.InnerClass inner2 = outer.new InnerClass();
    inner.show();
  }
}

  运行截图:                                                           

   

  常规内部类的特点,有如下:

  • 在内部类中可以访问外部类的任何修饰符修饰的成员变量和方法(包括private,static,fianl,public,protected,默认的.全部测试过)
  • 在内部类中访问外部类的方式有两种:
    • 直接访问,就是直接调用方法名或者变量名。
System.out.println(str2);
  • 通过下面这个格式访问:外部类名.this.(成员变量or方法)
System.out.println(OuterClass.this.str2);
  • 外部类也可以访问内部类的任何修饰符修饰的成员变量和方法(全部测试过)
  • 外部类不能直接访问内部类的成员变量和成员方法,在外部类中必须创建内部类的对象,通过内部类的对象去访问内部类的成员方法和变量。
InnerClass inner = new InnerClass();
System.out.println(inner.string1);
  • 内部类访问外部类的成员变量和方法,不管它们声明在内部类之后还是之前,只要是外部类的对象,内部类就能访问。
  • 在外围类中访问内部类的方法,同样和普通类一样,通过创建类的对象去访问。
  • 外围类创建内部类对象的方式,如下:
OuterClassName.InnerClassName  objName =
new  OuterClassName().new InnerClassName();

OuterClass.InnerClass inner = new OuterClass().new  InnerClass();
OuterClassName.InnerClassName  objName =
OuterClassObj.new InnerClassName();
OuterClass.InnerClass inner2 = outer.new  InnerClass();
  • 为什么要像vii点一样创建对象的分析:

  对于一个类来说,我们创建类的对象是new ClassName(),然后通过创出的对象去调用类的方法。而对于内部类来说,它是外部类的一部分,因此要创建内部类的对象则要通过外部类的对象去调用,然后在按照new ClassName()原则去创建内部类的对象即可。

 

三、局部内部类

局部内部类就是定义在方法中的类。

class AreaInnerClass{
public void test() {
  final int age = 10;
  class Inner{
    public void addOne(){
      System.out.println(age+1);
    }

    private void addTwo(){
      System.out.println(age+2);
    }
  }
    new Inner().addOne();
    new Inner().addTwo();
  }
}

public class AreaInnerClassDemo{
  public static void main(String[] args) {
    new AreaInnerClass().test();
  }
} 

局部内部类的特点:

  1. 局部内部类定义的位置在一个方法的内部。
  2. 局部内部类对于外界完全隐藏起来了,即使外部类也不能访问它。
  3. 局部内部类不能用private和public进行修饰,因为局部内部类的作用域被限制在方法块中,及时用private和public进行修饰也毫无意义。
  4. 局部内部类的访问,通过在方法中创建局部内部类的对象来调用内部类的方法。

 

四、匿名内部类

  匿名内部类其实就是对局部内部类的进一步的深入,假设只是创建一个类的对象,直接new className(){ .... },这样就不需要命名了。这种方式就叫做匿名内部类。

public class SecretInnerClassDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
new Object(){
void show(){
System.out.println("匿名内部类....");
}
}.show();
}
}

 

  a) 格式:

new className(){
// 写方法
}.funcName();

  b) 特点:

  1. new后面的className(类)必须是一个存在的类。(也就是说你new一个对象,那么就必须要存在一个具体类才能new)
  2. 存在前提,必须存在一个类,抽象类or接口

  c) 本质:

  是继承该类or接口的子类的匿名对象。(也就是说new className()或者new interfaceName(),返回的不是它们自身对象,返回而是它们的实现子类的对象,这个在匿名抽象类和匿名接口是最好理解,因为要重写接口和抽象类的方法,这个只有它们的子类能做,因此返回的是实现子类的对象)

 

五、静态内部类

  有时候,使用内部类只是为了把一个隐藏在另一个类的内部,并不需要内部类引用外围类对象。为此,可以将内部类声明为static,来取消产生的引用。

class StaticInnerClass {
private static int a1 = 10;
private static int b1 = 20;
static class Inner{
private int a = 10;
private int b = 20;

public int add(){
return a+b;
}

public int add2(){
return a1+b1;
}
}

public void test(){
System.out.println(new Inner().add());
}
}

public class StaticInnerClassDemo{
public static void main(String[] args) {
new StaticInnerClass().test();
}
}
原文地址:https://www.cnblogs.com/geore/p/7157782.html