内部类
6.1.什么是内部类?
将一个java类定义到另一个java类中的java类就是内部类。
外部类---包含内部类的类。
内部类---外部类中的类。
内部类编译后会形成一个新的字节码文件【外部类类名$内部类类型.class】
6.2.内部类有几种表现形式分别都是如何编写的?每一种内部类各自都有哪些特征?
1、成员内部类--类中方法外【成员变量】
例如:
package com.wangxing.test1;
//外部类
public class Hello {
public String hello_name="外部类实例变量";
public static String HELLO_STATIC_NAME="外部类类变量";
public Hello(){
System.out.println("外部类的构造方法");
//8.外内部类中的构造方法可以访问成员内部类的构造方法,实例方法/变量[对象方法],
World w=new World("world");
System.out.println(w.world_name);
w.worldShiliMethod();
}
public void helloShiliMethod(){
System.out.println("外部类的实例方法");
//9.外内部类中的实例方法可以访问成员内部类的构造方法,实例方法/变量[对象方法],
World w=new World("world");
System.out.println(w.world_name);
w.worldShiliMethod();
}
public static void helloStaticMethod(){
System.out.println("外部类的类方法");
//10.外内部类中的类方法不能访问成员内部类中的元素
//World w=new World("world");
//System.out.println(w.world_name);
//w.worldShiliMethod();
}
//成员内部类
//1.成员内部类可以使用任意的访问限制修饰符。
//2.成员内部类可以有实例变量、实例方法、构造方法,不能有静态元素。
public class World{
public String world_name="内部类实例变量";
public World(String testname){
System.out.println("内部类的构造方法,参数是=="+testname);
}
public void worldShiliMethod(){
System.out.println("内部类的实例方法");
}
public World(){
System.out.println("内部类的构造方法");
//3.成员内部类中的构造方法可以访问本成员内部类中的其他的构造方法【new】,
//可以访问实例变量/实例方法【对象.实例变量/方法,this.实例变量/方法,可以省略对象/this】。
World w=new World("world");
System.out.println(w.world_name);
System.out.println(this.world_name);
System.out.println(world_name);
w.worldShiliMethod();
this.worldShiliMethod();
worldShiliMethod();
//5.成员内部类中的构造方法可以访问外部类的构造方法,实例方法/变量,类方法/变量
//Hello.this--外部类对象
Hello h=new Hello();
System.out.println(h.hello_name);
System.out.println(Hello.this.hello_name);
System.out.println(hello_name);
h.helloShiliMethod();
Hello.this.helloShiliMethod();
helloShiliMethod();
System.out.println(h.HELLO_STATIC_NAME);
System.out.println(Hello.this.HELLO_STATIC_NAME);
System.out.println(Hello.HELLO_STATIC_NAME);
System.out.println(HELLO_STATIC_NAME);
h.helloStaticMethod();
Hello.this.helloStaticMethod();
Hello.helloStaticMethod();
helloStaticMethod();
}
public void worldTestShiliMethod(){
System.out.println("内部类的实例方法");
//4.成员内部类中的实例方法可以访问构造方法【new】,
//可以访问实例变量/方法【对象.实例变量/方法,this.实例变量/方法,可以省略对象/this】。
World w=new World("world");
System.out.println(w.world_name);
System.out.println(this.world_name);
System.out.println(world_name);
w.worldShiliMethod();
this.worldShiliMethod();
worldShiliMethod();
//6.成员内部类中的实例法可以访问外部类的构造方法,实例方法/变量,类方法/变量。
Hello h=new Hello();
System.out.println(h.hello_name);
System.out.println(Hello.this.hello_name);
System.out.println(hello_name);
h.helloShiliMethod();
Hello.this.helloShiliMethod();
helloShiliMethod();
System.out.println(h.HELLO_STATIC_NAME);
System.out.println(Hello.this.HELLO_STATIC_NAME);
System.out.println(Hello.HELLO_STATIC_NAME);
System.out.println(HELLO_STATIC_NAME);
h.helloStaticMethod();
Hello.this.helloStaticMethod();
Hello.helloStaticMethod();
helloStaticMethod();
}
}
}
在其他类中的访问情况:
package com.wangxing.test1;
//11.其他类中是可以访问成员内部类的,需要依赖外部类对象,注意访问限制修饰符
public class Other {
public Other(){
/*
//import com.wangxing.test1.Hello.World;
Hello h=new Hello(); //外部类的对象
World w1=h.new World(); //内部类对象
World w2=new Hello().new World();//内部类对象
System.out.println(w2.world_name);
w1.worldShiliMethod();
*/
Hello h=new Hello(); //外部类的对象
Hello.World w1=h.new World(); //内部类对象
Hello.World w2=new Hello().new World(); //内部类对象
System.out.println(w2.world_name);
w1.worldShiliMethod();
}
public void testOther(){
/*
//import com.wangxing.test1.Hello.World;
Hello h=new Hello(); //外部类的对象
World w1=h.new World(); //内部类对象
World w2=new Hello().new World();//内部类对象
System.out.println(w2.world_name);
w1.worldShiliMethod();
*/
Hello h=new Hello(); //外部类的对象
Hello.World w1=h.new World(); //内部类对象
Hello.World w2=new Hello().new World(); //内部类对象
System.out.println(w2.world_name);
w1.worldShiliMethod();
}
public static void testStaticOther(){
/*
//import com.wangxing.test1.Hello.World;
Hello h=new Hello(); //外部类的对象
World w1=h.new World(); //内部类对象
World w2=new Hello().new World();//内部类对象
System.out.println(w2.world_name);
w1.worldShiliMethod();
*/
Hello h=new Hello(); //外部类的对象
Hello.World w1=h.new World(); //内部类对象
Hello.World w2=new Hello().new World(); //内部类对象
System.out.println(w2.world_name);
w1.worldShiliMethod();
}
}
- 成员内部类可以使用任意的访问限制修饰符。
- 成员内部类可以有实例变量、实例方法、构造方法,不能有静态元素。
- 成员内部类中的构造方法可以访问其他的构造方法【new】,可以访问实例变量/方法【对象.实例变量/方法 ,this.实例变量/方法,可以省略对象/this】。
- 成员内部类中的实例方法可以访问构造方法【new】,可以访问实例变量/方法【对象.实例变量/方法 ,this.实例变量/方法,可以省略对象/this】。
- 成员内部类中的构造方法可以访问外部类的构造方法,实例方法/变量,类方法/变量。
- 成员内部类中的实例法可以访问外部类的构造方法,实例方法/变量,类方法/变量。
- 外内部类中的构造方法/实例法可以访问成员内部类的构造方法,实例方法/变量,外内部类中的类方法不能访问成员内部类。
- 其他类中是可以访问成员内部类的,需要依赖外部类对象,注意访问限制修饰符。
2.方法内部类--类中方法中【局部变量】
例如:
package com.wangxing.test1;
//1.方法内部类不能使用任何访问限制修饰
public class Hello {
public String hello_name="外部类实例变量";
public static String HELLO_STATIC_NAME="外部类类变量";
//10.外部类中不能访问方法内部类中的元素
public Hello(){
System.out.println("外部类的构造方法");
}
public void helloShiliMethod(){
System.out.println("外部类的实例方法");
}
public static void helloStaticMethod(){
System.out.println("外部类的类方法");
}
//2.方法内部类可以有实例变量/方法,构造方法,不能有静态元素。
public void testHello1(){
//方法的局部变量
String testvalue="value";
class WoldInner{
public String woldinner_name="方法内部类实例变量";
public WoldInner(String testname){
System.out.println("方法内部类的构造方法,参数是testname="+testname);
}
public void woldinnerShiliMethod1(){
System.out.println("方法内部类的实例方法");
}
public WoldInner(){
System.out.println("方法内部类的构造方法");
//3.方法内部类的构造方法中可以访问本类的构造方法,实例变量/方法【对象/this,也
//可以省略】
WoldInner inner=new WoldInner("test");
System.out.println(inner.woldinner_name);
System.out.println(this.woldinner_name);
System.out.println(woldinner_name);
inner.woldinnerShiliMethod1();
this.woldinnerShiliMethod1();
woldinnerShiliMethod1();
//5.方法内部类中的构造方法可以访问外部类的构造方法,实例方法/变量,类方法/变
//量。
Hello h=new Hello();
System.out.println(h.hello_name);
System.out.println(Hello.this.hello_name);
System.out.println(woldinner_name);
h.helloShiliMethod();
Hello.this.helloShiliMethod();
helloShiliMethod();
System.out.println(h.HELLO_STATIC_NAME);
System.out.println(Hello.this.HELLO_STATIC_NAME);
System.out.println(Hello.HELLO_STATIC_NAME);
System.out.println(HELLO_STATIC_NAME);
h.helloStaticMethod();
Hello.this.helloStaticMethod();
Hello.helloStaticMethod();
helloStaticMethod();
//7.方法内部类中的构造方法可以访问本方法的局部变量。
System.out.println(testvalue);
}
public void woldinnerShiliMethod2(){
System.out.println("方法内部类的实例方法");
//4.方法内部类的实例方法中可以访问本类的构造方法,实例变量/方法【对象/this,也
//可以省略】
WoldInner inner=new WoldInner("test");
System.out.println(inner.woldinner_name);
System.out.println(this.woldinner_name);
System.out.println(woldinner_name);
inner.woldinnerShiliMethod1();
this.woldinnerShiliMethod1();
woldinnerShiliMethod1();
//6.方法内部类中的实例方法可以访问外部类的构造方法,实例方法/变量,类方法/变
//量。
Hello h=new Hello();
System.out.println(h.hello_name);
System.out.println(Hello.this.hello_name);
System.out.println(woldinner_name);
h.helloShiliMethod();
Hello.this.helloShiliMethod();
helloShiliMethod();
System.out.println(h.HELLO_STATIC_NAME);
System.out.println(Hello.this.HELLO_STATIC_NAME);
System.out.println(Hello.HELLO_STATIC_NAME);
System.out.println(HELLO_STATIC_NAME);
h.helloStaticMethod();
Hello.this.helloStaticMethod();
Hello.helloStaticMethod();
helloStaticMethod();
//8.方法内部类中的实例方法可以访问本方法的局部变量。
System.out.println(testvalue);
}
}
//9.定义本方法内部类的方法中可以访问方法内部类中的构造方法,实例变量/实例方法【对象访
//问】
WoldInner inner=new WoldInner();
System.out.println(inner.woldinner_name);
inner.woldinnerShiliMethod1();
}
}
- 方法内部类不能使用任何访问限制修饰
- 方法内部类可以有实例变量/方法,构造方法,不能有静态元素。
- 方法内部类可以访问本类的实例变量/方法【对象/this,也可以省略】,构造方法
- 方法内部类可以访问本方法的局部变量【直接变量名称】
- 方法内部类可以访问外部类的构造方法,实例方法/变量,类方法/变量。
- 外部类是不能访问到方法内部类。
3.静态嵌套类---成员内部类使用static修饰【类变量】
package com.wangxing.test1;
//外部类
public class Hello {
public String hello_name="外部类实例变量";
public static String HELLO_STATIC_NAME="外部类类变量";
public Hello(){
System.out.println("外部类的构造方法");
//9.外内部类中的构造方法可以访问静态嵌套类的构造方法,实例方法/变量[对象访问],
//类方法/类变量[对象/类名访问]
World w=new World("world");
System.out.println(w.world_name);
w.worldShiliMethod();
System.out.println(w.world_static_name);
System.out.println(World.world_static_name);
w.worldStaticShiliMethod();
World.worldStaticShiliMethod();
}
public void helloShiliMethod(){
System.out.println("外部类的实例方法");
//9.外内部类中的实例方法可以访问静态嵌套类的构造方法,实例方法/变量[对象访问],
//类方法/类变量[对象/类名访问]
World w=new World("world");
System.out.println(w.world_name);
w.worldShiliMethod();
System.out.println(w.world_static_name);
System.out.println(World.world_static_name);
w.worldStaticShiliMethod();
World.worldStaticShiliMethod();
}
public static void helloStaticMethod(){
System.out.println("外部类的类方法");
//10.外内部类中的实例方法可以访问静态嵌套类的构造方法,实例方法/变量[对象访问],
//类方法/类变量[对象/类名访问]
World w=new World("world");
System.out.println(w.world_name);
w.worldShiliMethod();
System.out.println(w.world_static_name);
System.out.println(World.world_static_name);
w.worldStaticShiliMethod();
World.worldStaticShiliMethod();
}
//静态嵌套类
//1.静态嵌套类可以使用任意的访问限制修饰符。
//2.静态嵌套类可以有实例变量、实例方法、构造方法,类变量,类方法。
public static class World{
public String world_name="静态嵌套类实例变量";
public static String world_static_name="静态嵌套类类变量";
public World(String testname){
System.out.println("静态嵌套类的构造方法,参数是=="+testname);
}
public void worldShiliMethod(){
System.out.println("静态嵌套类的实例方法");
}
public static void worldStaticShiliMethod(){
System.out.println("静态嵌套类的类方法");
}
public World(){
System.out.println("静态嵌套类的构造方法");
//3.静态嵌套类中的构造方法可以访问本静态嵌套类中的其他的构造方法【new】,
//可以访问实例变量/实例方法【对象.实例变量/方法,this.实例变量/方法,可以省略对
//象/this】
//可以访问类变量/类方法【对象/类名.实例变量/方法,this.实例变量/方法,可以省略对
//象/this/类名】
World w=new World("world");
System.out.println(w.world_name);
System.out.println(this.world_name);
System.out.println(world_name);
w.worldShiliMethod();
this.worldShiliMethod();
worldShiliMethod();
System.out.println(w.world_static_name);
System.out.println(this.world_static_name);
System.out.println(World.world_static_name);
System.out.println(world_static_name);
w.worldStaticShiliMethod();
this.worldStaticShiliMethod();
World.worldStaticShiliMethod();
worldStaticShiliMethod();
//6.静态嵌套类中的构造方法可以访问外部类的构造方法
//可以访问外部类的实例方法/变量【只能对象】
//可以访问外部类的类方法/变量【对象/类名.类变量/类方法,可以省略对象/类名】
Hello h=new Hello();
System.out.println(h.hello_name);
h.helloShiliMethod();
System.out.println(h.HELLO_STATIC_NAME);
System.out.println(Hello.HELLO_STATIC_NAME);
System.out.println(HELLO_STATIC_NAME);
h.helloStaticMethod();
Hello.helloStaticMethod();
helloStaticMethod();
}
public void worldTestShiliMethod(){
System.out.println("静态嵌套类实例方法");
//4.静态嵌套类中的实例方法可以访问本静态嵌套类中的其他的构造方法【new】,
//可以访问实例变量/实例方法【对象.实例变量/方法,this.实例变量/方法,可以省略对
//象/this】
//可以访问类变量/类方法【对象/类名.实例变量/方法,this.实例变量/方法,可以省略对
//象/this/类名】
World w=new World("world");
System.out.println(w.world_name);
System.out.println(this.world_name);
System.out.println(world_name);
w.worldShiliMethod();
this.worldShiliMethod();
worldShiliMethod();
System.out.println(w.world_static_name);
System.out.println(this.world_static_name);
System.out.println(World.world_static_name);
System.out.println(world_static_name);
w.worldStaticShiliMethod();
this.worldStaticShiliMethod();
World.worldStaticShiliMethod();
worldStaticShiliMethod();
//7.静态嵌套类中的实例方法可以访问外部类的构造方法
//可以访问外部类的实例方法/变量【只能对象】
//可以访问外部类的类方法/变量【对象/类名.类变量/类方法,可以省略对象/类名】
Hello h=new Hello();
System.out.println(h.hello_name);
h.helloShiliMethod();
System.out.println(h.HELLO_STATIC_NAME);
System.out.println(Hello.HELLO_STATIC_NAME);
System.out.println(HELLO_STATIC_NAME);
h.helloStaticMethod();
Hello.helloStaticMethod();
helloStaticMethod();
}
public static void worldTestStaticShiliMethod(){
System.out.println("静态嵌套类的类方法");
//5.静态嵌套类中的类方法可以访问本静态嵌套类中的其他的构造方法【new】,
//可以访问实例变量/实例方法【对象.实例变量/方法】
//可以访问类变量/类方法【对象/类名.类变量/类方法,可以省略对象/类名】
World w=new World("world");
System.out.println(w.world_name);
w.worldShiliMethod();
System.out.println(w.world_static_name);
System.out.println(World.world_static_name);
System.out.println(world_static_name);
w.worldStaticShiliMethod();
World.worldStaticShiliMethod();
worldStaticShiliMethod();
//8.静态嵌套类中类方法可以访问外部类的构造方法
//可以访问外部类的实例方法/变量【只能对象】
//可以访问外部类的类方法/变量【对象/类名.类变量/类方法,可以省略对象/类名】
Hello h=new Hello();
System.out.println(h.hello_name);
h.helloShiliMethod();
System.out.println(h.HELLO_STATIC_NAME);
System.out.println(Hello.HELLO_STATIC_NAME);
System.out.println(HELLO_STATIC_NAME);
h.helloStaticMethod();
Hello.helloStaticMethod();
helloStaticMethod();
}
}
}
其他类访问静态嵌套类的情况:
package com.wangxing.test1;
//12.其他类中可以访问静态嵌套类中的构造方法,实例方法,实例变量,类方法,类变量
//注意是否导入静态嵌套类的程序包
public class Other {
public Other(){
/*
//import com.wangxing.test1.Hello.World;
World w1=new World(); //内部类对象
World w2=new World();//内部类对象
System.out.println(w2.world_name);
w1.worldShiliMethod();
System.out.println(w2.world_static_name);
System.out.println(World.world_static_name);
w1.worldStaticShiliMethod();
World.worldStaticShiliMethod();
*/
Hello.World w1=new Hello.World(); //内部类对象
Hello.World w2=new Hello.World();//内部类对象
System.out.println(w2.world_name);
w1.worldShiliMethod();
System.out.println(w2.world_static_name);
System.out.println(Hello.World.world_static_name);
w1.worldStaticShiliMethod();
Hello.World.worldStaticShiliMethod();
}
public void testOther(){
/*
//import com.wangxing.test1.Hello.World;
World w1=new World(); //内部类对象
World w2=new World();//内部类对象
System.out.println(w2.world_name);
w1.worldShiliMethod();
System.out.println(w2.world_static_name);
System.out.println(World.world_static_name);
w1.worldStaticShiliMethod();
World.worldStaticShiliMethod();
*/
Hello.World w1=new Hello.World(); //内部类对象
Hello.World w2=new Hello.World();//内部类对象
System.out.println(w2.world_name);
w1.worldShiliMethod();
System.out.println(w2.world_static_name);
System.out.println(Hello.World.world_static_name);
w1.worldStaticShiliMethod();
Hello.World.worldStaticShiliMethod();
}
public static void testStaticOther(){
/*
//import com.wangxing.test1.Hello.World;
World w1=new World(); //内部类对象
World w2=new World();//内部类对象
System.out.println(w2.world_name);
w1.worldShiliMethod();
System.out.println(w2.world_static_name);
System.out.println(World.world_static_name);
w1.worldStaticShiliMethod();
World.worldStaticShiliMethod();
*/
Hello.World w1=new Hello.World(); //内部类对象
Hello.World w2=new Hello.World();//内部类对象
System.out.println(w2.world_name);
w1.worldShiliMethod();
System.out.println(w2.world_static_name);
System.out.println(Hello.World.world_static_name);
w1.worldStaticShiliMethod();
Hello.World.worldStaticShiliMethod();
}
}
- 静态嵌套类中可以有构造方法,实例变量/方法,类变量/方法。
- 静态嵌套类中构造方法/实例方法可以访问本静态嵌套类中的构造方法,实例变量/方法,类变量/方法。
- 静态内部类中类方法可以访问本静态嵌套类中的构造方法,实例变量/方法【只能对象】,类变量/方法.
- 静态内部类中的构造方法/实例方法/类方法可以访问外部类的构造方法,实例变量/方法【只能对象】,类变量/方法。
- 静态嵌套类中不能有this.
- 外部类的构造方法/实例方法/类方法可以访问,静态内部类中构造方法,实例变量/方法【只能对象】,类变量/方法.
- 其他类中可以访问静态嵌套类【new 外部类类名.静态嵌套类名()】。注意访问限制修饰符
4.匿名内部类---【没有名字的内部类】就相当于某一个类/接口的子类,只是这个子类没有名字
- 继承式的匿名内部类
package com.wangxing.test1;
public class Person {
public void testPerson(){
System.out.println("Person类的实例方法");
}
}
package com.wangxing.test1;
public class TestPerson {
public static void main(String[] args) {
//Person person=new Person();
//person.testPerson();
//继承式的匿名内部类
//1.匿名内部类没有静态元素,没有构造方法
Person person1=new Person(){
public String name="zhangsan";
public void testMethod(){
System.out.println("匿名内部类的实例方法");
System.out.println("匿名内部类的实例变量=="+name);
}
};
/*
* new Person(){
..........
};
它就是Person类的子类,只是这个子类没有名字,所以才叫匿名内部类
*/
//上面的程序实际上是将Person类的子类对象赋值给Person这个父类的变量person1
//由此可知现在person1变量中保存的是一个上转型对象
//上转型对象只能访问被子类继承的方法,子类自己定义的方法不能访问
person1.testPerson();
//person1.testMethod(); 错误
}
}
当一个类中的方法参数是抽象类类型时,我们可以传递上转型对象/子类对象,如果不想额外的创建一个子类,这时我们使用匿名内部类也是可以的
package com.wangxing.test2;
public abstract class PersonBean {
public abstract void testPerson();
}
package com.wangxing.test2;
public class Test {
public void testMethod(PersonBean personbean){
System.out.println("普通类Test的实例方法");
//实际上调用的是被子类重写以后的方法
personbean.testPerson();
}
}
package com.wangxing.test2;
public class TestMain {
public static void main(String[] args) {
Test test=new Test();
//当方法的参数是抽象类类型的时候
//1.上转型对象
//2.抽象类的子类对象
//无论我们使用上转型对象/抽象类的子类对象对象都需要额外的创建出一个子类
//我们能不能在不去创建额外的子类的情况下,将参数传入??
//使用匿名内部类
test.testMethod(new PersonBean(){
@Override
public void testPerson() {
System.out.println("重写父类的抽象方法");
}
});
}
}
2.接口式的匿名内部类
package com.wangxing.test3;
public class Test {
public void testMethod(PersonInterface personbean){
System.out.println("普通类Test的实例方法");
//实际上调用的是被子类重写以后的方法
personbean.testPerson();
}
}
package com.wangxing.test3;
public interface PersonInterface {
void testPerson();
}
package com.wangxing.test3;
public class TestMain {
public static void main(String[] args) {
Test test=new Test();
//当方法的参数是接口类型的时候
//1.接口回调对象
//2.实现该接口的的子类对象
//无论我们使用接口回调对象/实现该接口的的子类对象对象都需要额外的创建出一个子类
//我们能不能在不去创建额外的子类的情况下,将参数传入??
//使用匿名内部类
test.testMethod(new PersonInterface(){
@Override
public void testPerson() {
System.out.println("重写接口的抽象方法");
}
});
}
}