指的是Java中可以将一个类定义在另一个类的内部
内部类可以定义在 类的内部(与类成员层次一致)
内部类可以定义在 方法/块内部(与类成员相差一个层次 与方法的局部变量一个层次)

1.成员内部类

1)内部类存在后,编译之后会生成两个class文件:OuterDemo.class 和 OuterDemo$InnerDemo.class
将一个类直接定义在类的里面 作为成员与属性或方法层次一致
2)可以与正常类一样 使用不同的修饰符修饰
3)若想要在内部类中通过对象调用外部类成员 需要 类名.this.外部类成员
4)若想要使用内部类的属性和方法 必须创建对象 通过外部类对象操作
5)成员内部类不能有static修饰的变量和方法 但是可以定义final
好处:
1.可以省略一个.java文件
2.成员内部类中可以访问到外部类中的所有成员 包括私有的

2.局部内部类(不太常用)

将一个类定义在方法/块里面 作为成员的内部结构 与临时的局部变量一个层次
局部内部类像是一个局部变量一样 不能用public proctected private及static等修饰,只能用abstract或final修饰
(因为这些都是修饰类和成员的,不能修饰局部变量,普通方法中不能定义static内部类)
在不同的方法中可以定义重名的局部内部类
局部内部类命名规则Demo$1InnerTestMethod Demo$2InnerTestMethod(局部内部类重名的情况下)
局部内部类可以访问外部类成员 局部内部类也能访问局部变量
局部内部类的局部变量需要加final修饰,如果不写默认也是这个
(因为类编译时会出现个类模板 类模板在编译加载时变量里的值是固定的 类加载好后里面存一个值 把变量值改后 类编译又得到另一个值 和原来的值对不上)

3.匿名内部类(常见)

成员匿名内部类
局部匿名内部类
public interface Test{
publicvoid test();
}
public class Son implements Test{
public void test(){
}
}
public static void main(String[] args){
Test t = new Test(){//因为接口不能创建对象 所以这个new的是Test接口的子类 子类中的方法就可以省略了
public void test(){
}
};
}

即(把中间子类继承的过程省略了)
public interface Test{
public void test();
}
public static void main(String[] args){
Test t = new Test(){
public void test(){
}
};
}
通常接口或抽象类的具体子类这样写
开发中为了省略一个类文件 上述写法比较常见
匿名内部类比较特殊 只有类体 没有类的所有结构(修饰符 名字 继承 实现都没有)
所以 匿名类不能用任何修饰符修饰 匿名内部类也没有构造方法

4.静态内部类

成员静态内部类
只能在类中定义 作为类的成员
静态内部类不需要外部类对象操作 通过正常的方法就可以直接创建内部类对象(因为静态成员在对象创建前就已经存在 即类加载时就已经有了)
静态成员不能访问非静态成员(自己类和外部类都不行)
静态内部类可以访问的是外部类的静态成员

  1. package test_innerclass;
  2. import sun.security.mscapi.CPublicKey;
  3. public class Demo {
  4. private String name = "这是外部类的普通属性";
  5. private static String name1 = "这是外部类的静态属性";
  6. public static void testDemo(){
  7. System.out.println("这是外部类的静态方法");
  8. }
  9. public void testInnerMethod(){
  10. //局部内部类 写在方法或者块里
  11. //只是临时存在 方法执行完就被回收了
  12. String myName = "局部外部类的属性";
  13. class InnerTestMethod{
  14. String myName = name;
  15. public void getName(){
  16. System.out.println(myName+name);
  17. }
  18. }
  19. }
  20. //成员内部类
  21. public class InnerDemo{
  22. private String name = "这是内部类的属性";
  23. public void testInnerDemo(){
  24. System.out.println("这是内部类的方法,"+Demo.this.name);
  25. //当属性同名时 要想在这里调用外部类的属性 可以用Demo.this.name
  26. //如果只写name 会根据就近原则 调用的是内部类的属性
  27. //不同名的话可以直接写属性名即可
  28. //调用内部类的属性只需要this.name
  29. testDemo();//可以直接调用外部类的方法
  30. }
  31. }
  32. //静态内部类
  33. public static class StaticInnerDemo{
  34. private String staticName = "这是静态内部类的属性";
  35. public void testStaticInnerDemo(){
  36. System.out.println("这是静态内部类的方法,"+staticName+","+name1);
  37. //因为是 静态的 所以它不能访问外部非静态的成员
  38. Demo.testDemo();//静态内部类只能访问外部类中的静态成员 非静态的无法访问
  39. }
  40. }
  41. }

主方法:

  1. package test_innerclass;
  2. import test_innerclass.Demo.InnerDemo;
  3. import test_innerclass.Demo.StaticInnerDemo;
  4. public class RunMain {
  5. public static void main(String[] args){
  6. //创建内部类对象
  7. InnerDemo innerDemo = new Demo().new InnerDemo();//导包后可以这样写
  8. //要是没有导包可以这样写
  9. // Demo demo = new Demo();
  10. // Demo.InnerDemo innerDemo = demo.new InnerDemo();
  11. //也可以直接
  12. // Demo.InnerDemo innerDemo = new Demo().new InnerDemo();
  13. innerDemo.testInnerDemo();//调用成员内部类方法
  14. //创建静态内部类对象
  15. Demo.StaticInnerDemo sid = new Demo.StaticInnerDemo();//没导包需要这样写
  16. //StaticInnerDemo sid = new StaticInnerDemo();//导包后可以这样写
  17. sid.testStaticInnerDemo();//调用静态内部类方法
  18. Outter.StaticInner si = new Outter.StaticInner();
  19. 应该这样看 Outter.StaticInner si = new [Outter.StaticInner]();
  20. Outter.StaticInner作为一个整体,所以说静态内部类不依赖于外部类的对象
  21. }
  22. }