1、什么是内部类

可以将一个类的定义放在另一个类的内部,这就是内部类。广义上我们将内部类分为四种:成员内部类,静态内部类、局部(方法)内部类、匿名内部类。

  1. /**
  2. * 我是一个外部类(外部是相对内部而言)
  3. */
  4. public class Outer{
  5. /**
  6. * 我是一个内部类
  7. */
  8. class Inner{
  9. //...
  10. }
  11. }

2、为什么使用内部类

使用内部类最吸引人的原因是:每个内部类都唔那个独立的继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。——《Think in java》

也就是说内部类拥有类的基本特征。(eg:可以继承父类,实现接口。)在实际问题中我们会遇到一些接口无法解决或难以解决的问题,此时我们可以使用内部类继承某个具体的或抽象的类,间接解决类无法多继承引起的一系列问题。(注:内部类可以嵌套内部类,但是这极大的破坏了代码的结构,这里不推荐使用。)

  1. /**
  2. 1. Outer类继承了ClassA,实现了IFunctionA
  3. */
  4. public class Outer extends ClassA implements IFunctionA{
  5. /**
  6. * Inner类继承了ClassB,实现了IFunctionB
  7. */
  8. public class Inner extends ClassB implements IfunctionB{
  9. //
  10. }
  11. }

除了上面的优点之外还有如下四点:

  • 内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
  • 内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。
  • 内部类提供了更好的封装,除了该外围类,其他类都不能访问。
  • 创建内部类对象的时刻并不依赖于外围类对象的创建。

具体来说,内部类信息(属性、方法)可以和外部类重名;内部类是具有类的基本特征的独立实体;可以利用访问修饰符隐藏内部类的实施细节,提供了更好的封装;静态内部类使用时可直接使用,不需先创造外部类。

简单总结:
image.png

一、成员内部类

1,外部类,内部类

  1. /**
  2. * 外部类、成员内部类的定义
  3. */
  4. public class Outer {
  5. private int outerVariable = 1;
  6. private int commonVariable = 2;
  7. private static int outerStaticVariable = 3;
  8. //省略getter/setter
  9. /**
  10. * 成员方法
  11. */
  12. public void outerMethod() {
  13. System.out.println("我是外部类的outerMethod方法");
  14. }
  15. /**
  16. * 静态方法
  17. */
  18. public static void outerStaticMethod() {
  19. System.out.println("我是外部类的outerStaticMethod静态方法");
  20. }
  21. /**
  22. * 内部类
  23. */
  24. public class Inner {
  25. private int commonVariable = 20;
  26. /**
  27. * 构造方法
  28. */
  29. public Inner() {
  30. }
  31. /**
  32. * 成员方法,访问外部类信息(属性、方法)
  33. */
  34. public void innerShow() {
  35. //当和外部类冲突时,直接引用属性名,是内部类的成员属性
  36. System.out.println("内部的commonVariable:" + commonVariable);
  37. //内部类访问外部属性
  38. System.out.println("outerVariable:" + outerVariable);
  39. //当和外部类属性名重叠时,可通过外部类名.this.属性名
  40. System.out.println("外部的commonVariable:" + Outer.this.commonVariable);
  41. System.out.println("outerStaticVariable:" + outerStaticVariable);
  42. //访问外部类的方法
  43. outerMethod();
  44. outerStaticMethod();
  45. }
  46. }
  47. /**
  48. * 外部类访问内部类信息
  49. */
  50. public void outerShow() {
  51. Inner inner = new Inner();
  52. inner.innerShow();
  53. }
  54. }

2.其他类使用成员内部类

  1. /*
  2. * 其他类使用成员内部类
  3. */
  4. public class Other {
  5. public static void main(String[] args) {
  6. //外部类对象
  7. Outer outer = new Outer();
  8. //创造内部类对象
  9. Outer.Inner inner = outer.new Inner();
  10. inner.innerShow();
  11. /*
  12. * 可在Outer中定义get方法,获得Inner对象,那么使用时,只需outer.getInnerInstance()即可。
  13. * public Inner getInnerInstance(Inner类的构造方法参数){
  14. * return new Inner(参数);
  15. * }
  16. */
  17. }
  18. }

3.小结

  1. 可以是任何的访问修饰符。
  2. 内部类的内部不能有静态信息。
  3. 内部类也是类,该继承继承,该重写重写,该重载重载,this和super随便用。
  4. 外部类如何访问内部类信息,必须new之后打点访问。
  5. 内部类可以直接使用外部类的任何信息,如果属性或者方法发生冲突,调用外部类.this.属性或者方法。

二、静态内部类

  1. /**
  2. * 外部类、内部类定义
  3. */
  4. public class Outer {
  5. private int outerVariable = 1;
  6. /**
  7. * 外部类定义的属性(重名)
  8. */
  9. private int commonVariable = 2;
  10. private static int outerStaticVariable = 3;
  11. static {
  12. System.out.println("Outer的静态块被执行了……");
  13. }
  14. /**
  15. * 成员方法
  16. */
  17. public void outerMothod() {
  18. System.out.println("我是外部类的outerMethod方法");
  19. }
  20. /*
  21. * 静态方法
  22. */
  23. public static void outerStaticMethod() {
  24. System.out.println("我是外部类的outerStaticMethod静态方法");
  25. }
  26. /**
  27. * 静态内部类
  28. */
  29. public static class Inner {
  30. /**
  31. * 成员信息
  32. */
  33. private int innerVariable = 10;
  34. private int commonVariable = 20;
  35. static {
  36. System.out.println("Outer.Inner的静态块执行了……");
  37. }
  38. private static int innerStaticVariable = 30;
  39. /**
  40. * 成员方法
  41. */
  42. public void innerShow() {
  43. System.out.println("innerVariable:" + innerVariable);
  44. System.out.println("内部的commonVariable:" + commonVariable);
  45. System.out.println("outerStaticVariable:"+outerStaticVariable);
  46. outerStaticMethod();
  47. }
  48. /**
  49. * 静态方法
  50. */
  51. public static void innerStaticShow() {
  52. //被调用时会先加载Outer类
  53. outerStaticMethod();
  54. System.out.println("outerStaticVariable"+outerStaticVariable);
  55. }
  56. }
  57. /**
  58. * 外部类的内部如何和内部类打交道
  59. */
  60. public static void callInner() {
  61. System.out.println(Inner.innerStaticVariable);
  62. Inner.innerStaticShow();
  63. }
  64. }

2、其他类使用成员内部类

  1. public class Other {
  2. public static void main(String[] args) {
  3. //访问静态内部类的静态方法,Inner类被加载,此时外部类未被加载,独立存在,不依赖于外围类。
  4. Outer.Inner.innerStaticShow();
  5. //访问静态内部类的成员方法
  6. Outer.Inner oi = new Outer.Inner();
  7. oi.innerShow();
  8. }
  9. }

3、小结

  1. 内部可以包含任意的信息。
  2. 静态内部类的方法只能访问外部类的static关联的信息
  3. 利用 外部类.内部类 引用=new 外部类.内部类(); 然后利用引用.成员信息(属性、方法)调用。
  4. 访问内部类的静态信息,直接外部类.内部类.静态信息就可以了。
  5. 静态内部类可以独立存在,不依赖于其他外围类。

局部内部类

1、内部类,外部类

  1. /**
  2. * 外部类、内部类
  3. */
  4. public class Outer {
  5. /**
  6. * 属性和方法
  7. */
  8. private int outerVariable = 1;
  9. /**
  10. * 外部类定义的属性
  11. */
  12. private int commonVariable = 2;
  13. /**
  14. * 静态的信息
  15. */
  16. private static int outerStaticVariable = 3;
  17. /**
  18. * 成员外部方法
  19. */
  20. public void outerMethod() {
  21. System.out.println("我是外部类的outerMethod方法");
  22. }
  23. /**
  24. * 静态外部方法
  25. */
  26. public static void outerStaticMethod() {
  27. System.out.println("我是外部类的outerStaticMethod静态方法");
  28. }
  29. /**
  30. * 程序的入口
  31. */
  32. public static void main(String[] args) {
  33. Outer outer = new Outer();
  34. outer.outerCreatMethod(100);
  35. }
  36. /**
  37. * 成员方法,内部定义局部内部类
  38. */
  39. public void outerCreatMethod(int value) {
  40. /**
  41. * 女性
  42. */
  43. boolean sex = false;
  44. /**
  45. * 局部内部类,类前不能有访问修饰符
  46. */
  47. class Inner {
  48. private int innerVariable = 10;
  49. private int commonVariable = 20;
  50. /**
  51. * 局部内部类方法
  52. */
  53. public void innerShow() {
  54. System.out.println("innerVariable:" + innerVariable);
  55. //局部变量
  56. System.out.println("是否男性:" + sex);
  57. System.out.println("参数value:" + value);
  58. //调用外部类的信息
  59. System.out.println("outerVariable:" + outerVariable);
  60. System.out.println("内部的commonVariable:" + commonVariable);
  61. System.out.println("外部的commonVariable:" + Outer.this.commonVariable);
  62. System.out.println("outerStaticVariable:" + outerStaticVariable);
  63. outerMethod();
  64. outerStaticMethod();
  65. }
  66. }
  67. //局部内部类只能在方法内使用
  68. Inner inner = new Inner();
  69. inner.innerShow();
  70. }
  71. }

2、小结

  1. 类前不能有访问修饰符。
  2. 仅在此方法内使用。
  3. 无法创造静态信息。
  4. 可以直接访问方法内的局部变量和参数(有限制),但是不能更改。
  5. 可以随意的访问外部类的任何信息。

四、匿名内部类

1、定义接口

  1. /**
  2. * 接口中方法默认为public
  3. */
  4. public interface IAnimal{
  5. void speak();
  6. }

2、匿名内部类的使用

  1. /**
  2. * 外部内、内部类
  3. */
  4. public class Outer {
  5. public static IAnimal getInnerInstance(String speak){
  6. return new IAnimal(){
  7. @Override
  8. public void speak(){
  9. System.out.println(speak);
  10. }};
  11. //注意上一行的分号必须有
  12. }
  13. public static void main(String[] args){
  14. //调用的speak()是重写后的speak方法。
  15. Outer.getInnerInstance("小狗汪汪汪!").speak();
  16. }
  17. }
  1. 匿名内部类是没有访问修饰符的。
  2. 使用匿名内部类时,这个new之后的类首先是要存在的,其次我们要重写new后的类的某个或某些方法。
  3. 匿名内部类访问方法参数时也有和局部内部类同样的限制。
  4. 匿名内部类没有构造方法。

此文部分转载自:https://blog.csdn.net/weixin_42762133/article/details/82890555
更详细请移步。