概述
- 内部类信息(属性、方法)可以和外部类重名;
- 内部类是具有类的基本特征的独立实体;
- 可以利用访问修饰符隐藏内部类的实施细节,提供了更好的封装;
- 静态内部类使用时可直接使用,不需先创造外部类。
- 内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
- 内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。
- 内部类提供了更好的封装,除了该外围类,其他类都不能访问。
- 创建内部类对象的时刻并不依赖于外围类对象的创建。
成员内部类
- 作为成员存在,可以被任意权限修饰符修饰
- 可以调用外部所有信息
- 外部类使用,new对象打点
- 其他类使用:
外部类.内部类 内部对象 = 外部对象.new 内部类() OuterTest2 out = new OuterTest2(); OuterTest2.Inner inner = out.new Inner();
先new外部类,在new内部类,最后打点使用 也可:外部类.内部类 变量名 = new 外部类().new 内部类();
- 可以和外部类属性、方法重名,调用时外部类名this属性/方法即可
- 有类的基本特征
public class Outertest1 {
private int num = 100;
public Outertest1() {
System.out.println("OuterTest1构造函数");
}
public class Inner1{
private int num = 200;
public Inner1() {
System.out.println("Inner1构造函数");
}
public void test() {
//可以直接调用外部类私有成员
System.out.println("OuterTest1的n"+Outertest1.this.num);
System.out.println("Inner1的n"+num);
System.out.println(string);//外部类不重名变量
}
}
public static void main(String[] args) {
Outertest1 n = new Outertest1();
Inner1 n1 = n.new Inner1();//使用外部类对象创建内部类对象
System.out.println("OuterTest1的n"+n.num);
System.out.println("Inner1的n"+n1.num);
n1.test();
System.out.println("--------");
n.outer();
// OuterTest1构造函数
// Inner1构造函数
// OuterTest1的n100
// Inner1的n200
// OuterTest1的n100
// Inner1的n200
//要先new 外部类,然后 new 内部类
// Inner1 n2 = new Inner1();
}
public void outer() {
Inner1 n3 = new Inner1();//直接调用内部类
n3.test();
}
// Inner1构造函数
// OuterTest1的n100
// Inner1的n200
}
注意:main方法中不能new 内部类,但是外部类中的方法可以直接new 内部类
- 首先你的内部类不是静态的对吧(不是static class)
- 而main方法是静态的
- main 方法是个静态方法,而 静态 类不是个静态内部类,所以不能直接初始化
- 对main方法而言,虽然写在类中,它是游离于任何类之外的(就跟C++一样,单独一个main方法),因此某类的非静态内部类对它而言是不直接可见的,也就无法直接访问
内部类可以调用成员方法,静态方法
public class OuterTest2 {
private static int OuterStaicInt = 12;
//成员方法
public void OuterMathod() {
System.out.println("Outer的成员方法");
}
//静态方法
public static void OuterStaticMathod() {
System.out.println("Outer的静态方法");
}
public class Inner {
//方法才能调用方法,而System.out.println(x); 是一个内置方法,所以只能放到方法里去调用,不能写在类里.
//System.out.println("OuterStaticInt: "+OuterStaicInt);
public void InnerMathod() {
//访问外部类静态变量
System.out.println("OuterStaticInt: "+OuterStaicInt);
OuterMathod();
OuterStaticMathod();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
OuterTest2 out = new OuterTest2();
OuterTest2.Inner inner = out.new Inner();
inner.InnerMathod();
}
}
注意:方法才能调用方法,而System.out.println(x); 是一个内置方法,所以只能放到方法里去调用,不能写在类里.
静态内部类
- 作为静态成员属性存在,可以被任意权限修饰符修饰
- 只可以调用外部static相关联的信息
- 外部类使用时,类名信息即可
- 其他类使用时,OuterInner inner=new OuterInner;然后打点调用成员信息。静态信息,直接使用OuterInner信息
public class OuterTest3 {
private static String staticString = "外部类静态变量staticString";
private String string = "外部变量";
private static String outerStaticString = "外部静态变量outerStaticString";
private static void OuterStaticMathod() {
System.out.println("outer中的静态方法");
}
private void OuterMathod() {
System.out.println("outer中的方法");
}
public static class Inner{
private static String staticString = "内部类静态变量staticString";
public void Test() {
// System.out.println(string);//外部类中变量非静态,不能用,报错,非静态类可直接调用
System.out.println(new OuterTest3().string);//外部变量
//内部类中没有重名变量,可直接调变量
System.out.println(outerStaticString);//外部静态变量outerStaticString
//静态类中调用重名静态变量:类.静态变量,非静态类调用重名变量需要:类.this.变量
System.out.println(OuterTest3.staticString);//外部类静态变量staticString
System.out.println(staticString);//内部类静态变量staticString
OuterStaticMathod();//outer中的静态方法
// OuterMathod();//外部类中方法非静态,不能调用,报错
}
public static void StaticTest() {
OuterStaticMathod();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
//静态内部类使用时与内部成员类不同
//OuterTest3.Inner inner = new OuterTest3().new Inner();
OuterTest3.Inner inner = new Inner();
//或
// OuterTest3 outer = new OuterTest3();
// OuterTest3.Inner inner = new Inner();
inner.Test();
// OuterTest3.Inner.Test();//非静态方法不可以这样
OuterTest3.Inner.StaticTest();
outer();
}
public static void outer() {
// Inner.Test();//不能调用非静态方法
System.out.println(OuterTest3.Inner.staticString);
Inner.StaticTest();
}
// 外部变量
// 外部静态变量outerStaticString
// 外部类静态变量staticString
// 内部类静态变量staticString
// outer中的静态方法
// outer中的静态方法
// 内部类静态变量staticString
// outer中的静态方法
}
注意:
- 静态内部类不能直接访问外部类的非静态成员,但,可以通过new 外部类().成员的方式访问
- 如果外部类的静态成员与内部类的静态成员相同, 可以通过"类名.静态成员"来访问外部类的静态成员;如果不同,可以直接调用外部类的静态成员名。
- 创建静态内部类的对象时,不需要外部类的对象,可以直接创建;
- 利用 外部类.内部类 引用=new 外部类.内部类(); 然后利用引用.成员信息(属性、方法)调用。
OuterTest3.Inner inner = new Inner();
- 访问内部类的静态信息,直接外部类.内部类.静态信息就可以了。
OuterTest3.Inner.StaticTest();
方法,变量都可访问
局部内部类
- 存在于方法之中,只能在方法中使用,具备类的基本特征,类前不能有访问权限
- 无法创造静态信息,因为在方法结束后,内存需要释放
- 可以直接访问方法的局部变量,但是无法修改。
- 可以随意访问外部的所有信息
匿名内部类
如果接口的实现类(或者是父类的子类)只需要使用唯一的一次,那么这种情况下就可以省略掉该类的定义,而改为使用匿名内部类
匿名内部类的定义格式:
接口名称 对象名 = new 接口名称() {
// 覆盖重写所有抽象方法
};
- new代表创建对象的动作
- 接口名称就是匿名内部类需要实现哪个接口
- {…}这才是匿名内部类的内容
public interface MyInterface {
void Mathod();
}
public class MyInterfaceImpl implements MyInterface {
@Override
public void Mathod() {
// TODO Auto-generated method stub
System.out.println("接口中Mathad");
}
}
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyInterface m = new MyInterfaceImpl();//实现类
m.Mathod();
//匿名类可不写MyInterfaceImpl直接实现
MyInterface m2 = new MyInterface() {//不用实现类,只用到一次
@Override
public void Mathod() {
// TODO Auto-generated method stub
System.out.println("匿名内部类中Mathod");
}
};
m2.Mathod();//对象为m2
new MyInterface() {
@Override
public void Mathod() {
System.out.println("匿名对象匿名类中的Mathod");
}
}.Mathod();//匿名对象
}
}
例2:
public interface Animal {
public void speak();
}
public class OuterTest {
public static Animal getInnerInstance(String speak) {
return new Animal() {
@Override
public void speak(){
System.out.println(speak);
}
};
}
public static void main(String[] args) {
// TODO Auto-generated method stub
getInnerInstance("aaa").speak();
}
}