指的是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.静态内部类
成员静态内部类
只能在类中定义 作为类的成员
静态内部类不需要外部类对象操作 通过正常的方法就可以直接创建内部类对象(因为静态成员在对象创建前就已经存在 即类加载时就已经有了)
静态成员不能访问非静态成员(自己类和外部类都不行)
静态内部类可以访问的是外部类的静态成员
package test_innerclass;
import sun.security.mscapi.CPublicKey;
public class Demo {
private String name = "这是外部类的普通属性";
private static String name1 = "这是外部类的静态属性";
public static void testDemo(){
System.out.println("这是外部类的静态方法");
}
public void testInnerMethod(){
//局部内部类 写在方法或者块里
//只是临时存在 方法执行完就被回收了
String myName = "局部外部类的属性";
class InnerTestMethod{
String myName = name;
public void getName(){
System.out.println(myName+name);
}
}
}
//成员内部类
public class InnerDemo{
private String name = "这是内部类的属性";
public void testInnerDemo(){
System.out.println("这是内部类的方法,"+Demo.this.name);
//当属性同名时 要想在这里调用外部类的属性 可以用Demo.this.name
//如果只写name 会根据就近原则 调用的是内部类的属性
//不同名的话可以直接写属性名即可
//调用内部类的属性只需要this.name
testDemo();//可以直接调用外部类的方法
}
}
//静态内部类
public static class StaticInnerDemo{
private String staticName = "这是静态内部类的属性";
public void testStaticInnerDemo(){
System.out.println("这是静态内部类的方法,"+staticName+","+name1);
//因为是 静态的 所以它不能访问外部非静态的成员
Demo.testDemo();//静态内部类只能访问外部类中的静态成员 非静态的无法访问
}
}
}
主方法:
package test_innerclass;
import test_innerclass.Demo.InnerDemo;
import test_innerclass.Demo.StaticInnerDemo;
public class RunMain {
public static void main(String[] args){
//创建内部类对象
InnerDemo innerDemo = new Demo().new InnerDemo();//导包后可以这样写
//要是没有导包可以这样写
// Demo demo = new Demo();
// Demo.InnerDemo innerDemo = demo.new InnerDemo();
//也可以直接
// Demo.InnerDemo innerDemo = new Demo().new InnerDemo();
innerDemo.testInnerDemo();//调用成员内部类方法
//创建静态内部类对象
Demo.StaticInnerDemo sid = new Demo.StaticInnerDemo();//没导包需要这样写
//StaticInnerDemo sid = new StaticInnerDemo();//导包后可以这样写
sid.testStaticInnerDemo();//调用静态内部类方法
Outter.StaticInner si = new Outter.StaticInner();
应该这样看 Outter.StaticInner si = new [Outter.StaticInner]();
将Outter.StaticInner作为一个整体,所以说静态内部类不依赖于外部类的对象
}
}