1.为什么要使用内部类

采用内部类,可以更好地隐藏细节和内部结构,封装性更好,让程序的结构更加合理;
如果不用内部类,每个类都单独作为一个类,类的种类太多,调用起来麻烦;

1.非静态内部类

  1. package InnerClassTest;
  2. /**
  3. * ClassName:OuterClass
  4. * Package:InnerClassTest
  5. * Description:
  6. *
  7. * @Date:2021/8/30 13:13
  8. * @Author:zhanglei@3417529439@qq.com
  9. */
  10. public class OuterClass {
  11. private String outerName;
  12. public OuterClass(){
  13. outerName="outerClassName";
  14. }
  15. public void display(){
  16. System.out.println("OuterClass Display");
  17. System.out.println(outerName);
  18. }
  19. //只有先new出来外部类的对象才能访问非静态内部类
  20. public class InnerClass{
  21. private String innerName;
  22. public InnerClass(){
  23. innerName="innerClassName";
  24. }
  25. public void display(){
  26. System.out.println("InnerClass Display");
  27. System.out.println(innerName);
  28. }
  29. }
  30. public static void main(String[] args) {
  31. OuterClass outerClass=new OuterClass();
  32. outerClass.display();
  33. // InnerClass innerClass = new InnerClass(); //这样没法编译通过
  34. InnerClass innerClass = outerClass.new InnerClass();//非静态内部类的创建需要借助外部类的对象才能创建
  35. innerClass.display();
  36. }
  37. }
  38. OuterClass Display
  39. outerClassName
  40. InnerClass Display
  41. innerClassName

注意一个点:
对于非静态内部类,必须先有外部类的对象才能生成内部类的对象
使用1(在外部类中调用内部类):
OuterClass outerClass=new OuterClass();
InnerClass innerClass = outerClass.new InnerClass();

使用2(在其他类中调用内部类):
public class Test1 {
public static void main(String[] args) {
OuterClass.InnerClass i1=new OuterClass().new InnerClass();
i1.display();
}
}

1.1 少见的局部内部类

image.png

2.静态内部类

  1. package InnerClassTest;
  2. /**
  3. * ClassName:OuterClass
  4. * Package:InnerClassTest
  5. * Description:
  6. *
  7. * @Date:2021/8/30 13:13
  8. * @Author:zhanglei@3417529439@qq.com
  9. */
  10. public class OuterClass {
  11. private String outerName;
  12. public OuterClass(){
  13. outerName="outerClassName";
  14. }
  15. public void display(){
  16. System.out.println("OuterClass Display");
  17. System.out.println(outerName);
  18. }
  19. //可以直接访问静态内部类,无需先new出外部类的对象
  20. public static class InnerClass{
  21. private String innerName;
  22. public InnerClass(){
  23. innerName="innerClassName";
  24. }
  25. public void display(){
  26. System.out.println("InnerClass Display");
  27. System.out.println(innerName);
  28. }
  29. }
  30. public static void main(String[] args) {
  31. OuterClass outerClass=new OuterClass();
  32. outerClass.display();
  33. InnerClass innerClass = new InnerClass();
  34. innerClass.display();
  35. }
  36. }

使用1:在外部类中调用内部类
InnerClass innerClass = new InnerClass();
使用2:在其他类中调用内部类
public class Test1 {
public static void main(String[] args) {
OuterClass.InnerClass i1=new OuterClass.InnerClass();
i1.display();
}
}

注意new OuterClass.InnerClass()和new OuterClass().InnerClass();的区别
前者是OuterClass.InnerClass作为一个整体
后者是OuterClass和InnerClass各自作为一个整体

3.匿名内部类

1.先定义一个接口
public interface MyInterface {
public void test();
}
2.传统方法:定义一个类去继承该接口,实现test方法
public class MyImplements implements MyInterface{
@Override
public void test() {
System.out.println(“test!”);
}
}
3.匿名内部类:不显式定义一个类去继承该接口,而是直接new

  1. public class AnonymousTest {
  2. public static void main(String[] args) {
  3. //传统方法
  4. MyInterface myImplements = new MyImplements();
  5. myImplements.test();
  6. //匿名内部类直接使用
  7. new MyInterface(){
  8. @Override
  9. public void test() {
  10. System.out.println("大家好");
  11. }
  12. }.test();
  13. //匿名内部类赋值给一个引用变量再使用
  14. MyInterface myInterface=new MyInterface(){
  15. @Override
  16. public void test() {
  17. System.out.println("我是VAE");
  18. }
  19. };
  20. myInterface.test();
  21. }
  22. }
  23. test!
  24. 大家好
  25. 我是VAE

匿名内部类:
匿名:没有显式定义一个类该实现接口
内部类:确实是类的内部定义的

易混淆点:
匿名内部类容易跟lambda表达式联系在一起;
lambda表达式要求对应的接口只有一个抽象方法(继承Object的抽象方法不考虑),
那匿名内部类的接口是否也是只能有一个抽象方法,答案是否定的

  1. public interface MyInterface {
  2. public void test();
  3. public void test1();
  4. }
  1. public class MyImplements implements MyInterface{
  2. @Override
  3. public void test() {
  4. System.out.println("test!");
  5. }
  6. @Override
  7. public void test1() {
  8. System.out.println("test1!");
  9. }
  10. }
  1. public class AnonymousTest {
  2. public static void main(String[] args) {
  3. MyInterface myImplements = new MyImplements();
  4. myImplements.test1();
  5. new MyInterface(){
  6. @Override
  7. public void test() {
  8. System.out.println("大家好");
  9. }
  10. @Override
  11. public void test1() {
  12. System.out.println("你好");
  13. }
  14. }.test1();
  15. MyInterface myInterface=new MyInterface(){
  16. @Override
  17. public void test() {
  18. System.out.println("我是VAE");
  19. }
  20. @Override
  21. public void test1() {
  22. System.out.println("你是qq");
  23. }
  24. };
  25. myInterface.test1();
  26. }
  27. }
  28. test1!
  29. 你好
  30. 你是qq

匿名内部类要实现的接口有多少抽象方法就实现多少抽象方法