当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类。

1、什么是内部类

Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B就是外部类.

  1. class Person{
  2. String name = "李雷";
  3. int age;
  4. //静态成员内部类
  5. static class Dog{
  6. String name;
  7. int age;
  8. public void show(){
  9. System.out.println("卡拉是条狗");
  10. }
  11. }
  12. //非静态成员内部类
  13. class Bird{
  14. String name = "杜鹃";
  15. public Bird(){
  16. }
  17. public void sing(){
  18. System.out.println("我是一只猫头鹰");
  19. Person.this.eat();//调用外部类的非静态属性
  20. System.out.println(age);
  21. }
  22. }

2、内部类的分类

成员内部类 和 局部内部类 (方法内、代码块内、构造器内)

3、成员内部类能干什么?

3.1、作为外部类的成员

  • 调用外部类的结构
  • 可以被static修饰
  • 可以被4种权限修饰符修饰

    3.2、作为一个类

  • 类内可以定义属性、方法、构造器

  • 可以被final修饰,表示此类不能被继承。言外之意,不使用final就可以被继承
  • 可以被abstract修饰

    4、内部类关注的问题

    4.1、如何实例化成员内部类的对象

    1. public class InnerClassTest {
    2. public static void main(String[] args) {
    3. //创建Dog实例(静态的成员内部类)
    4. Person.Dog dog = new Person.Dog();
    5. dog.show();
    6. //创建Bird实例(非静态的成员内部类)
    7. Person p = new Person(); //先将
    8. Person.Bird bird = p.new Bird();
    9. bird.sing();
    10. System.out.println();
    11. bird.display("喜鹊");
    12. }

    4.2、如何在成员内部类中区分调用外部类的结构

    方法中的形参:直接形参名
    内部类的属性:this.属性名
    外部类的属性:外部类名.this.属性名 ```java public class InnerClassTest { public static void main(String[] args) {

    1. //创建Dog实例(静态的成员内部类)
    2. Person.Dog dog = new Person.Dog();
    3. dog.show();
    4. //创建Bird实例(非静态的成员内部类)

    // Person.Bird bird = new Person.Bird();

    1. Person p = new Person();
    2. Person.Bird bird = p.new Bird();
    3. bird.sing();
    4. System.out.println();
    5. bird.display("喜鹊");

    } } class Person{ String name = “李雷”; int age;

    public void eat(){

    1. System.out.println("人,吃饭");

    }

    //静态成员内部类 static class Dog{

    1. String name;
    2. int age;
    3. public void show(){
    4. System.out.println("卡拉是条狗");

    // eat();

    1. }

    }

    //非静态成员内部类 class Bird{

    1. String name = "杜鹃";
    2. public Bird(){
    3. }
    4. public void sing(){
    5. System.out.println("我是一只猫头鹰");
    6. Person.this.eat();//调用外部类的非静态属性
    7. eat();
    8. System.out.println(age);
    9. }
    10. public void display(String name){
    11. System.out.println(name); //方法的形参
    12. System.out.println(this.name); //内部类的属性
    13. System.out.println(Person.this.name); //外部类的属性
    14. }

    } public void method(){

    1. //局部内部类
    2. class AA{
    3. }

    }

    {

    1. //局部内部类
    2. class BB{
    3. }

    }

    public Person(){

    1. //局部内部类
    2. class CC{
    3. }

    } }

  1. <a name="pSihN"></a>
  2. ## 4.3、开发中局部内部类的使用 见《InnerClassTest1.java》
  3. ```java
  4. public class InnerClassTest1 {
  5. // 开发中很少见
  6. public void method(){
  7. // 局部内部类
  8. class AA{
  9. }
  10. }
  11. // 返回一个实现了Comparable接口的类的对象
  12. public Comparable getComparable(){
  13. // 创建一个实现了Comparable接口的类:局部内部类
  14. //方式一:
  15. // class MyComparable implements Comparable{
  16. //
  17. // @Override
  18. // public int compareTo(Object o) {
  19. // return 0;
  20. // }
  21. //
  22. // }
  23. //
  24. // return new MyComparable();
  25. //方式二:
  26. return new Comparable(){
  27. @Override
  28. public int compareTo(Object o) {
  29. return 0;
  30. }
  31. };
  32. }
  33. }

5、匿名内部类

匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例。
一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。

  1. /*
  2. * 1.匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例。
  3. * 一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
  4. *
  5. * 2.格式:
  6. * new 父类构造器(实参列表)|实现接口(){
  7. * //匿名内部类的类体部分
  8. * }
  9. *
  10. * 3.匿名内部类的特点
  11. * > 匿名内部类必须继承父类或实现接口
  12. * > 匿名内部类只能有一个对象
  13. * > 匿名内部类对象只能使用多态形式引用
  14. */
  15. interface Product{
  16. public double getPrice();
  17. public String getName();
  18. }
  19. public class AnonymousTest{
  20. public void test(Product p){
  21. System.out.println("购买了一个" + p.getName() + ",花掉了" + p.getPrice());
  22. }
  23. public static void main(String[] args) {
  24. AnonymousTest ta = new AnonymousTest();
  25. //调用test方法时,需要传入一个Product参数,
  26. //此处传入其匿名实现类的实例
  27. ta.test(new Product(){
  28. public double getPrice(){
  29. return 567.8;
  30. }
  31. public String getName(){
  32. return "AGP显卡";
  33. }
  34. });
  35. }
  36. }
  1. public class InnerClassTest {
  2. // public void onCreate(){
  3. //
  4. // int number = 10;
  5. //
  6. // View.OnClickListern listener = new View.OnClickListener(){
  7. //
  8. // public void onClick(){
  9. // System.out.println("hello!");
  10. // System.out.println(number);
  11. // }
  12. //
  13. // }
  14. //
  15. // button.setOnClickListener(listener);
  16. //
  17. //}
  18. /*
  19. * 在局部内部类的方法中(比如:show)如果调用局部内部类所声明的方法(比如:method)中的局部变量(比如:num)的话,
  20. * 要求此局部变量声明为final的。
  21. *
  22. * jdk 7及之前版本:要求此局部变量显式的声明为final的
  23. * jdk 8及之后的版本:可以省略final的声明
  24. *
  25. */
  26. public void method(){
  27. //局部变量
  28. int num = 10;
  29. class AA{
  30. public void show(){
  31. // num = 20; //Local variable num defined in an enclosing scope must be final or effectively final
  32. System.out.println(num);
  33. }
  34. }
  35. }
  36. }