内部类
1.什么是内部类?
将一个java类定义到另一个java类中的java类就是内部类。
外部类—包含内部类的类。
内部类—外部类中的类。
内部类编译后会形成一个新的字节码文件【外部类类名$内部类类型.class】
2.内部类有几种表现形式分别都是如何编写的?每一种内部类各自都有哪些特征?
1、成员内部类–类中访问外【成员变量】
外部类与内部类的调用关系
package com.wangxiang.test1;
//成员内部类
public class NeiBuClass {
//实例变量
public String name="zhangsan";
//静态变量
public String NAME="lisi";
//无参构造方法
public NeiBuClass(){
//外部类构造方法调用内部类的构造方法
NeiBuLei nb2=new NeiBuLei(30);
System.out.println("外部类调用内部类实例变量num"+nb2.num);
nb2.ShiLiMethod();//外部类调用内部类实例方法
System.out.println("无参构造方法");
}
//有参构造方法
public NeiBuClass(int name){
System.out.println("有参构造方法name=="+name);
}
//实例方法
public void WaiBuLei(){
//外部类实例方法调用内部类的实例方法
NeiBuLei nb2=new NeiBuLei(30);
System.out.println("外部类调用内部类实例变量num"+nb2.num);
nb2.ShiLiMethod();//外部类调用内部类实例方法
System.out.println("无参构造方法");
System.out.println("外部类的实例方法");
}
//静态方法
public static void StaticWaiBuLei(){
//外部类构造方法调用内部类的构造方法
//报错,外部类静态方法不能调用内部类的内容
/*NeiBuLei nb2=new NeiBuLei();
System.out.println("外部类调用内部类实例变量num"+nb2.num);
nb2.ShiLiMethod();//外部类调用内部类实例方法
System.out.println("无参构造方法");
System.out.println("外部类的静态方法");*/
}
//成员内部类
public class NeiBuLei{
public int num=10;
// public static int num2=20;//报错,所以成员内部类中不能有静态元素
//无参构造方法
public NeiBuLei(){
//构造方法调用外部类的内容
NeiBuClass nb1=new NeiBuClass(20);//内部类可以访问其他构造方法
System.out.println("内部类访问外部类实例变量name=="+name);
System.out.println("内部类访问外部类静态变量NAME=="+NAME);
NeiBuClass.this.WaiBuLei();//外部类.this.外部方法
nb1.WaiBuLei();
nb1.StaticWaiBuLei();
}
//有参构造方法
public NeiBuLei(int num3){
System.out.println("内部类的有参构造方法num3=="+num3);
}
public void ShiLiMethod(){
//实例方法调用外部类的内容
NeiBuClass nb1=new NeiBuClass();//内部类可以访问其他构造方法
System.out.println("内部类访问外部类实例变量name=="+name);
System.out.println("内部类访问外部类静态变量NAME=="+NAME);
NeiBuClass.this.WaiBuLei();//外部类.this.外部方法
nb1.WaiBuLei();
nb1.StaticWaiBuLei();
}
// public static void StaticMethod(){
// } //报错,所以成员内部类中不能有静态元素
}
}
其他类与内部类的调用关系
package com.wangxiang.test1;
//成员内部类
public class NeiBuClass {
//实例变量
public String name="zhangsan";
//静态变量
public String NAME="lisi";
//无参构造方法
public NeiBuClass(){
//外部类构造方法调用内部类的构造方法
NeiBuLei nb2=new NeiBuLei(30);
System.out.println("外部类调用内部类实例变量num"+nb2.num);
nb2.ShiLiMethod();//外部类调用内部类实例方法
System.out.println("无参构造方法");
}
//有参构造方法
public NeiBuClass(int name){
System.out.println("有参构造方法name=="+name);
}
//实例方法
public void WaiBuLei(){
//外部类实例方法调用内部类的实例方法
NeiBuLei nb2=new NeiBuLei(30);
System.out.println("外部类调用内部类实例变量num"+nb2.num);
nb2.ShiLiMethod();//外部类调用内部类实例方法
System.out.println("无参构造方法");
System.out.println("外部类的实例方法");
}
//静态方法
public static void StaticWaiBuLei(){
//外部类构造方法调用内部类的构造方法
//报错,外部类静态方法不能调用内部类的内容
/*NeiBuLei nb2=new NeiBuLei();
System.out.println("外部类调用内部类实例变量num"+nb2.num);
nb2.ShiLiMethod();//外部类调用内部类实例方法
System.out.println("无参构造方法");
System.out.println("外部类的静态方法");*/
}
//成员内部类
public class NeiBuLei{
public int num=10;
// public static int num2=20;//报错,所以成员内部类中不能有静态元素
//无参构造方法
public NeiBuLei(){
//构造方法调用外部类的内容
NeiBuClass nb1=new NeiBuClass(20);//内部类可以访问其他构造方法
System.out.println("内部类访问外部类实例变量name=="+name);
System.out.println("内部类访问外部类静态变量NAME=="+NAME);
NeiBuClass.this.WaiBuLei();//外部类.this.外部方法
nb1.WaiBuLei();
nb1.StaticWaiBuLei();
}
//有参构造方法
public NeiBuLei(int num3){
System.out.println("内部类的有参构造方法num3=="+num3);
}
public void ShiLiMethod(){
//实例方法调用外部类的内容
NeiBuClass nb1=new NeiBuClass();//内部类可以访问其他构造方法
System.out.println("内部类访问外部类实例变量name=="+name);
System.out.println("内部类访问外部类静态变量NAME=="+NAME);
NeiBuClass.this.WaiBuLei();//外部类.this.外部方法
nb1.WaiBuLei();
nb1.StaticWaiBuLei();
}
// public static void StaticMethod(){
// } //报错,所以成员内部类中不能有静态元素
}
}
总结:
- 1.成员内部类可以使用任意的访问限制修饰符。
- 2.成员内部类可以有实例变量、实例方法、构造方法,不能有静态元素。
- 3.成员内部类中的构造方法可以访问其他的构造方法【new】,可以访问实例变量/方法【对象.实例变量/方法 ,this.实例变量/方法,可以省略对象/this】。
- 4.成员内部类中的实例方法可以访问构造方法【new】,可以访问实例变量/方法【对象.实例变量/方法 ,this.实例变量/方法,可以省略对象/this】。
- 5.成员内部类中的构造方法可以访问外部类的构造方法,实例方法/变量,类方法/变量。
- 6.成员内部类中的实例法可以访问外部类的构造方法,实例方法/变量,类方法/变量。
- 7.外内部类中的构造方法/实例法可以访问成员内部类的构造方法,实例方法/变量,外内部类中的类方法不能访问成员内部类。
- 8.其他类中是可以访问成员内部类的,需要依赖外部类对象,注意访问限制修饰符。
2.方法内部类–类中方法中【局部变量】
package com.wangxing.test1;
public class Hello {
public int helloid=1000;
public Hello() {}
public void helloMehtod() {}
public static void helloStaticMehtod() {}
public void helloMethod1(int num){
String name="zhangsan";
class World{
public int worldid=1001;
//public static String worldname="zhangsan";
public World() {
World w=new World(1);
System.out.println("worldid=="+w.worldid);
System.out.println("worldid=="+this.worldid);
System.out.println("worldid=="+worldid);
w.worldMethod2();
this.worldMethod2();
worldMethod2();
//4.方法内部类可以访问本方法的局部变量【直接变量名称】
System.out.println("name=="+name);
}
public World(int a) {
Hello h=new Hello();
System.out.println("helloid=="+h.helloid);
System.out.println("helloid=="+Hello.this.helloid);
System.out.println("helloid=="+helloid);
h.helloMehtod();
Hello.this.helloMehtod();
helloMehtod();
h.helloStaticMehtod();
Hello.this.helloStaticMehtod();
Hello.helloStaticMehtod();
helloStaticMehtod();
}
public void worldMethod1() {
World w=new World(1);
System.out.println("worldid=="+w.worldid);
System.out.println("worldid=="+this.worldid);
System.out.println("worldid=="+worldid);
w.worldMethod2();
this.worldMethod2();
worldMethod2();
//4.方法内部类可以访问本方法的局部变量【直接变量名称】
System.out.println("name=="+name);
Hello h=new Hello();
System.out.println("helloid=="+h.helloid);
System.out.println("helloid=="+Hello.this.helloid);
System.out.println("helloid=="+helloid);
h.helloMehtod();
Hello.this.helloMehtod();
helloMehtod();
h.helloStaticMehtod();
Hello.this.helloStaticMehtod();
Hello.helloStaticMehtod();
helloStaticMehtod();
}
public void worldMethod2() {}
//public static void worldStaticMethod() {}
}
}
}
总结:
- 1.方法内部类不能使用任何访问限制修饰
- 2.方法内部类可以有实例变量/方法,构造方法,不能有静态元素。
- 3.方法内部类可以访问本类的实例变量/方法【对象/this,也可以省略】,构造方法
- 4.方法内部类可以访问本方法的局部变量【直接变量名称】
- 5.方法内部类可以访问外部类的构造方法,实例方法/变量,类方法/变量
- 6.外部类是不能访问到方法内部类。
3.静态嵌套类—成员内部类使用static修饰【类变量】
package com.wangxing.test1;
public class Hello {
public int helloid=1000;
public static String helloname="lisi";
public Hello() {
World w=new World();
System.out.println("worldid=="+w.worldid);
w.worldMethod1();
System.out.println("worldname=="+w.worldname);
System.out.println("worldname=="+World.worldname);
w.worldStaricMethod1();
World.worldStaricMethod1();
}
public Hello(int num) {
}
public void helloMehtod1() {
World w=new World();
System.out.println("worldid=="+w.worldid);
w.worldMethod1();
System.out.println("worldname=="+w.worldname);
System.out.println("worldname=="+World.worldname);
w.worldStaricMethod1();
World.worldStaricMethod1();
}
public void helloMehtod2() {
}
public static void helloStaticMehtod1() {
World w=new World();
System.out.println("worldid=="+w.worldid);
w.worldMethod1();
System.out.println("worldname=="+w.worldname);
System.out.println("worldname=="+World.worldname);
w.worldStaricMethod1();
World.worldStaricMethod1();
}
public static void helloStaticMehtod2() {
}
public static class World{
//静态内部类可以有实例变量
public int worldid=1001;
//静态内部类可以有类变量
public static String worldname="zhangsan";
//静态内部类可以有构造方法
public World() {
World w=new World(100);
System.out.println("worldid=="+w.worldid);
System.out.println("worldid=="+this.worldid);
System.out.println("worldid=="+worldid);
w.worldMethod2();
this.worldMethod2();
worldMethod2();
System.out.println("worldname=="+w.worldname);
System.out.println("worldname=="+this.worldname);
System.out.println("worldname=="+World.worldname);
System.out.println("worldname=="+worldname);
w.worldStaricMethod2();
this.worldStaricMethod2();
World.worldStaricMethod2();
worldStaricMethod2();
}
public World(int num1) {
Hello hello=new Hello(12);
System.out.println("helloid=="+hello.helloid);
hello.helloMehtod2();
System.out.println("helloname=="+hello.helloname);
System.out.println("helloname=="+Hello.helloname);
System.out.println("helloname=="+helloname);
hello.helloStaticMehtod2();
Hello.helloStaticMehtod2();
helloStaticMehtod2();
}
//静态内部类可以有实例方法
public void worldMethod1() {
World w=new World(100);
System.out.println("worldid=="+w.worldid);
System.out.println("worldid=="+this.worldid);
System.out.println("worldid=="+worldid);
w.worldMethod2();
this.worldMethod2();
worldMethod2();
System.out.println("worldname=="+w.worldname);
System.out.println("worldname=="+this.worldname);
System.out.println("worldname=="+World.worldname);
System.out.println("worldname=="+worldname);
w.worldStaricMethod2();
this.worldStaricMethod2();
World.worldStaricMethod2();
worldStaricMethod2();
}
public void worldMethod2() {
Hello hello=new Hello(12);
System.out.println("helloid=="+hello.helloid);
hello.helloMehtod2();
System.out.println("helloname=="+hello.helloname);
System.out.println("helloname=="+Hello.helloname);
System.out.println("helloname=="+helloname);
hello.helloStaticMehtod2();
Hello.helloStaticMehtod2();
helloStaticMehtod2();
}
//静态内部类可以有类方法
public static void worldStaricMethod1() {
World w=new World(100);
System.out.println("worldid=="+w.worldid);
w.worldMethod2();
System.out.println("worldname=="+w.worldname);
System.out.println("worldname=="+World.worldname);
System.out.println("worldname=="+worldname);
w.worldStaricMethod2();
World.worldStaricMethod2();
worldStaricMethod2();
}
public static void worldStaricMethod2() {
Hello hello=new Hello(12);
System.out.println("helloid=="+hello.helloid);
hello.helloMehtod2();
System.out.println("helloname=="+hello.helloname);
System.out.println("helloname=="+Hello.helloname);
System.out.println("helloname=="+helloname);
hello.helloStaticMehtod2();
Hello.helloStaticMehtod2();
helloStaticMehtod2();
}
}
}
package com.wangxing.test1;
public class Test1 {
public Test1() {
/*
//import com.wangxing.test1.Hello.World;
World w=new Hello.World();
w.worldMethod1();
w.worldStaricMethod1();
Hello.World.worldStaricMethod1();
*/
Hello.World w2=new Hello.World();
}
public void myMethod() {
/*
//import com.wangxing.test1.Hello.World;
World w=new Hello.World();
w.worldMethod1();
w.worldStaricMethod1();
Hello.World.worldStaricMethod1();
*/
Hello.World w2=new Hello.World();
}
public static void main(String[] args) {
/*
//import com.wangxing.test1.Hello.World;
World w=new Hello.World();
w.worldMethod1();
w.worldStaricMethod1();
Hello.World.worldStaricMethod1();
*/
Hello.World w2=new Hello.World();
}
}
总结:
- 1.静态嵌套类中可以有构造方法,实例变量/方法,类变量/方法。
- 2.静态嵌套类中构造方法/实例方法可以访问本静态嵌套类中的构造方法,实例变量/方法,类变量/方法。
- 3.静态内部类中类方法可以访问本静态嵌套类中的构造方法,实例变量/方法【只能对象】,类变量/方法.
- 4.静态内部类中的构造方法/实例方法/类方法可以访问外部类的构造方法,实例变量/方法【只能对象】,类变量/方法。
- 5.静态嵌套类中不能有this.
- 6.外部类的构造方法/实例方法/类方法可以访问,静态内部类中构造方法,实例变量/方法【只能对象】,类变量/方法.
- 7.其他类中可以访问静态嵌套类【new 外部类类名.静态嵌套类名()】。注意访问限制修饰符
4.匿名内部类—【没有名字的内部类】就相当于某一个类/接口的子类,只是这个子类没有名字
- 1.继承式的匿名内部类
package com.wangxing.test1;
public class MyClass {
public void testMyClass() {
System.out.println("MyClass类的实例方法");
}
}
package com.wangxing.test1;
public class Test1 {
public static void main(String[] args) {
MyClass mc=new MyClass() {
@Override
public void testMyClass() {
System.out.println("重写MyClass类的testMyClass方法");
}
};
mc.testMyClass();
}
}
当一个类中的方法参数是抽象类类型时,我们可以传递上转型对象/子类对象,如果不想额外的创建一个子类,这时我们使用匿名内部类也是可以的
package com.wangxing.test1;
public abstract class TestClass {
public abstract void testTClass();
}
package com.wangxing.test1;
public class MyClass {
public void testMyClass2(TestClass tc) {
tc.testTClass();
}
package com.wangxing.test1;
public class Test1 {
public static void main(String[] args) {
MyClass mc=new MyClass();
mc.testMyClass2(new TestClass() {
@Override
public void testTClass() {
System.out.println("重写抽象类TestClass的抽象方法");
}
});
}
}
- 2.接口式的匿名内部类
package com.wangxing.test2;
public interface MyInterface {
void testMethod();
}
package com.wangxing.test2;
public class Test2 {
public static void main(String[] args) {
MyInterface inter=new MyInterface() {
@Override
public void testMethod() {
System.out.println("重写接口的抽象方法");
}
};
}
}
当一个类中的方法参数是接口类型时,我们可以传递接口回调对象/子类对象,如果不想额外的创建一个接口的子类,这时我们使用匿名内部类也是可以的。
package com.wangxing.test2;
public interface MyInterface {
void testMethod();
}
package com.wangxing.test2;
public class DoClass {
public void testDoMethod(MyInterface inter) {
inter.testMethod();
}
}
package com.wangxing.test2;
public class Test2 {
public static void main(String[] args) {
DoClass dc=new DoClass();
dc.testDoMethod(new MyInterface() {
@Override
public void testMethod() {
System.out.println("重写接口的抽象方法");
}
});
}
}
优点:避免创建额外的独立子类
缺点:不易理解,不易阅读