非匿名内部类:编译之后,内部类会生存独自的.class文件,名称为外部类名$内部类名
匿名内部类:以外部类名$数字来命名
(一)静态内部类
- 静态内部类可以包含静态成员和非静态成员
- 静态内部类可以调用外部类的静态方法和静态属性。不可以调用普通方法和普通属性
- 在不相关的类中,可以直接创建静态内部类的对象(不需要通过所属外部类)
- 静态内部类和外部类联系很少,也就是命名空间上的联系
package xidia.lili.testinnerclass;
//可以以包的形式导入
import xidia.lili.testinnerclass.OutClass.StaticNestClass;
/**
* * 测试内部类
*/
public class Demo01 {
public static void main(String[] args) {
OutClass o = new OutClass();
// OutClass.StaticNestClass sss=new OutClass.StaticNestClass();
StaticNestClass ss = new StaticNestClass();
}
}
class OutClass {
int b = 10;
static String str = "aaa";
public void test() {
StaticNestClass s = new StaticNestClass();// 在外部类可以直接创建对象
}
// 静态内部类
public static class StaticNestClass {
int a = 0;
public void test() {
// System.out.println(b);//不能访问非静态属性
System.out.println(str);
}
}
}
(二)成员内部类(普通内部类)
- 相当于外部类的一个成员变量
- 可以访问外部类的所有成员,包括private修饰的成员
- 成员内部类的this指内部类对象,要使用外部类的对象,借助外部类名.this.成员内部类的对象是一定要绑在外部类的对象上,现有外部类对象再有内部类对象
- 成员内部类中不能有静态方法
package xidia.lili.testinnerclass;
import xidia.lili.testinnerclass.Outer.Inner;
public class Demo02 {
public static void main(String[] args) {
// 创建内部类对象
//先创建外部类对象
Outer one=new Outer();
//Inner i=new Inner();//成员内部类对象不可以这样创建,import也不行
Inner i=one.new Inner();
i.test();
}
}
class Outer{
private int a=0;
static int b=0;
public void tt(){
Inner i=new Inner();//在外部类中可以,因为你调用这个方法,肯定存在外部类对象
}
public class Inner{//可以加修饰符
//static int c=0;//不能定义静态成员,除非定义为final,也不能有静态方法,如果存在静态成员,可以直接通过类名调用。那就脱离外部类,与成员内部类初衷不符合。
static final int d=2;
void test(){
System.out.println(a);//任意访问外部类的成员
System.out.println("内部对象"+this);
System.out.println("外部对象"+Outer.this);
}
}
}
输出:
(三)方法内部类
- 只能定义非静态成员
- 不可以在内部类前加修饰符,只对该方法可见。因此定义方法内部类之后,想用的话直接在方法内实例化,顺序是先申明后实例化
- 地位与方法中的局部变量类似
- 不能再方法内部类中使用方法中的局部变量,方法与类对象的生命周期不一致。 除非是常量
- class Out{
int a=3;
public void test(){
int b=9;
final int MAX=100;
class Inner{//不能加修饰符。只在方法内部可见
int c=10;
//static int d=0;//不可以定义静态变量
public void test(){
System.out.print(c);
//System.out.print(b);//不可以调用方法的局部变量 方法体与静态对象生命周期不一样 除非是常量
System.out.print(MAX);
System.out.print(a);
}
}
}
}
(四)匿名内部类
- 根据内部类的位置判断是成员内部类还是方法内部类
- 接口式
- 参数式
- 继承式
- package xidia.lili.testinnerclass;
public class Demo04 {
public static void main(String []args){
Outer1 o=new Outer1();
o.test();
}
}
class Outer1{
public void test02(Car c){
c.run();
}
public void test(){
//在方法中定义匿名内部类 所以是特殊的方法内部类
Runnable r=new Runnable(){//匿名内部类(接口式写法) 创建一个匿名类对象和实现匿名类放在一起
@Override
public void run() {
System.out.println("匿名内部类(接口式写法) ");
}
};
r.run();
Car c=new Car(){
@Override
public void run() {
System.out.println("子类的汽车在跑");
}//匿名内部类(继承式)相当于子类重写父类Car的test方法
};
c.run();
test02(new Car(){
@Override
public void run() {
System.out.print("匿名内部类(参数式写法) ");
}
});
}
}
class Car{
public void run(){
System.out.print("父类的汽车在跑");
}
}