什么是内部类?
关于内部类,其实就是在一个类或者一个方法里面在创建一个新的类,内部的类,就叫做内部类。嵌套在内部的类就叫做内部类,不在内部的就叫做外部类。内部类也是封装的一种体现。
一般的结构类型:
class OuterClass{
/...../
class InnerClass{
/...../
}
}
只有在class花括号内的创建的类,才叫做内部类。而且内部类与外部类虽然共用同一个java源文件,但是经过编译后,内部类会形成单独的字节码文件。
内部类一般分为几种:成员内部类,局部内部类,匿名内部类。
1.成员内部类
1.1实例内部类
即未被static修饰的成员内部类
class OutClass{ public int data1 = 10; private int data2 = 20; class InnerClass{ public int data3 = 30; public int data4 = 40; } public void testInner(){ System.out.println(data1); //10 System.out.println(data2); //20 System.out.println(data3); //30 } } }public class Test { public static void main(String[] args) { OutClass outClass =new OutClass(); OutClass.InnerClass innerClass = outClass.new InnerClass(); System.out.println(outClass.data1); //System.out.println(outClass.data2);error innerClass.testInner(); } }
1.想要调用内部类里的变量,就要先通过实例外部类,再实例内部类,我们才能拿到内部类的变量与方法。实例内部类对象必须在先有外部类对象前提下才能创建
2.内部类可以直接对外部类的变量与方法进行访问,但是再main方法中需要先实例对象,而且在实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束。
3.实例内部类的非静态方法中包含了一个指向外部类对象的引用,在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须:外部类名称.this.同名成员来访问。,如
class OutClass{
public int data1 = 10;
private int data2 = 20;
public int data3 = 300;
class InnerClass{
public int data3 = 30;
public int data4 = 40; }
public void testInner(){
System.out.println(data1); //10
System.out.println(data2); //20
System.out.println(data3); //30System.out.println(this.data3); //30
System.out.println(OuterClass.this.data3); //300
}
4.外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象。
class OutClass{
public int data1 = 10;
private int data2 = 20;
public int data3 = 300;
class InnerClass{
public int data3 = 30;
public int data4 = 40;
}
public void InnerTest(){
InnerClass innerClass = new InnerClass();
iSystem.out.println(InnerClass.data4); //40
}
5.实例内部类中不能含有直接被static修饰的成员,需要加上final与static一起修饰才能正常运行。
实例内部类的缺点在于每次想要实例内部类时,总需要先实例一个外部类对象,才能对内部类进行实例 。
1.2静态内部类
即被static修饰的内部类成员
class OuterClass2{
static class InnerClass2{
public void testInner() {
System.out.println("静态内部类!!!");
}
}
}
public class Test2 {
public static void main(String[] args) {
OuterClass2.InnerClass2 innerClass2 =new OuterClass2.InnerClass2();
innerClass2.testInner();
}
}
运行结果:
而使用静态内部类的好处就在于不用先实例化外部类才能使用内部类,可以直接将静态内部类实例化并且使用。所以我们创建静态内部类对象时,不需要先创建外部类对象。
但是,在静态内部类中只能直接访问外部类中的静态成员,而我们如果想访问其它非静态成员,就必须在静态内部类中先将外部类实例化,再用“外部类名.+访问对象”的方式对外部类成员进行访问。
class OuterClass2{
public int data1 = 10;
private int data2 = 20;
public int data3 = 30;
static class InnerClass2{
public int data3 = 300;
private int data4 = 40;
public void testInner() {
System.out.println("静态内部类!!!");
OuterClass2 outerClass2 = new OuterClass2();
System.out.println(outerClass2.data1);
System.out.println(outerClass2.data2);
System.out.println(outerClass2.data3);
System.out.println(data3);
System.out.println(data4);
}
}
}
public class Test2 {
public static void main(String[] args) {
OuterClass2.InnerClass2 innerClass2 =new OuterClass2.InnerClass2();
innerClass2.testInner();
}
}
运行结果:
2.局部内部类
class OuterClass3{
public void test() {
class InnerClass {
public int data1 = 10;
}
InnerClass innerClass = new InnerClass();
System.out.println(innerClass.data1);
}
}
public class Test3 {
public static void main(String[] args) {
OuterClass3 outerClass3 = new OuterClass3();
outerClass3.test();
}
}
运行结果:
这种局部内部类几乎很少被使用到。
1.局部内部类只能在所定义的方法体内部使用。
2.局部内部类不能被public,static等修饰符修饰。
3.匿名内部类
其实就是一种没有名字的内部类,其作用可以使代码更加简化。当我们在代码中想要用到某一个类或接口时,需要创建一个新的实现类。如果我们只希望这个类实现一次,那么我们如果创建一个新的类,就会有点麻烦。但是如果我们用匿名内部类的话,就可以直接进行重写,不需要创建新的类。
interface Innerclass{
void show();
}
public class Test4 {
public static void main(String[] args) {
new Innerclass(){
@Override
public void show() {
System.out.println("匿名内部类!");
}
}.show();
}
}
还需要注意的是,在匿名内部类当中,访问的变量是不能改变的。
比如:
interface Innerclass{ void show(); } public class Test4 { public static void main(String[] args) { int a = 10; new Innerclass(){ @Override public void show() { a = 99; //error System.out.println("匿名内部类!" + a); } }.show(); } }
关于匿名内部类,会在后面的多线程学习会使用很多匿名内部类的语法格式。 而匿名内部类不仅可以用于自己创建的接口,还可以用于编译器本身自带的接口。Comparable接口