1、内部类:
把类定义在其他类的内部,我们称之为内部类内部类有哪些特点:
(1)内部类可以访问外部类的成员,包括私有
(2)外部类要想访问内部类的成员,必须要创建内部类的对象class Outer{ private int num = 10; class Inner{ public void show(){ System.out.println(num); } } public void fun(){ // show(); //创建内部类对象 Inner inner = new Inner(); inner.show(); } } public class InnerClassDemo1 { public static void main(String[] args) { Outer outer = new Outer(); // outer.show(); outer.fun(); } }
2、按照内部类在类中定义的位置不同,可以分为如下两种格式:
成员位置(成员内部类)
局部位置(局部内部类)class Outer2{ //定义在成员的位置上(成员内部类) class Inner2{ } public void fun(){ //定义在局部范围内(局部内部类) class Inner3{ } } } public class InnerClassDemo2 { }
3、成员内部类:
(1)定义在类的成员位置上
(2)内部类可以方法外部类的成员,包括私有的class Outer3{ private int num = 10; class Inner{ public void show(){ System.out.println(num); } } } public class InnerClassDemo3 { public static void main(String[] args) { //需求:我现在要想在测试类中访问到Inner类中的show方法,咋办,就必须得创建对象 // Inner inner3 = new Inner(); //正确创建成员内部类对象的格式 //外部类名.成员内部类名 对象名 = new 外部类名().new 成员内部类名(); // Outer3.Inner oi3 = new Outer3().new Inner(); // oi3.show(); Outer3 outer3 = new Outer3(); Outer3.Inner inner = outer3.new Inner(); inner.show(); } }
4、成员内部类常见的修饰符:
private: 其他类不能直接创建内部类的对象,要想使用被private修饰内部类成员,必须 在本类中间接的创建对象调用
static: 内部类如果是被satic修饰的时候,只能访问外部类中静态成员class Outer4 { // private int num = 200; private static int num = 200; // private class Inner4{ // public void fun(){ // System.out.println(num); // } // } static class Inner4 { public static void fun() { System.out.println(num); } } // public void show() { // Inner4 inner4 = new Inner4(); // inner4.fun(); // } } public class InnerClassDemo4 { public static void main(String[] args) { // Outer4.Inner4 oi4 = new Outer4().new Inner4(); // oi4.fun(); // Outer4 outer4 = new Outer4(); // outer4.show(); // Outer4.Inner4 oi4 = new Outer4.new Inner4(); //当内部类是被静态所修饰的时候,出现了另外一种创建内部类的方式 //格式如下: //外部类名.内部类名 对象名 = new 外部类名.内部类名(); // Outer4.Inner4 oi4 = new Outer4.Inner4(); // oi4.fun(); //直接通过类名直接调用 Outer4.Inner4.fun(); } }
5、例题:
class Outer {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(?);
System.out.println(??);
System.out.println(???);
}
}
}
在控制分别输出:30,20,10class Outer5{ public int num = 10; class Inner5 { public int num = 20; public void show() { int num = 30; System.out.println(num); //30 System.out.println(this.num); //20 //Outer5和Inner5不是继承关系,没有super关键字 // System.out.println(super.num); //10 // System.out.println(new Outer5().num); System.out.println(Outer5.this.num); } } } public class InnerClassDemo5 { public static void main(String[] args) { Outer5.Inner5 oi5 = new Outer5().new Inner5(); oi5.show(); } }
6、 局部内部类:
(1)定义在方法中的类
(2)局部内部类可以直接方法外部类中所有成员
(3)要想使用局部内部类中的方法,在定义局部内部类的成员方法中,创建局部内部 类对象调用方法。class Outer6{ private int num = 10; public void fun(){ int num2 = 20; class Inner6{ int num3 = 300; public void show(){ num3 = 30; //在局部内部类中引用的本地的变量必须是最终变量或者实际上的最终变量 //通过反编译工具观察发现,存在局部内部类的方法中定义的局部变量自动加上了final关键字 //在JDK1.8之后会自动加上final关键字 // num2 = 22; num = 44; System.out.println(num); System.out.println(num2); System.out.println(num3); } } Inner6 inner6 = new Inner6(); inner6.show(); } } public class InnerClassDemo6 { public static void main(String[] args) { Outer6 outer6 = new Outer6(); outer6.fun(); } }
7、匿名内部类
(1)语句定义格式:
new 类名(可以是抽象类也可以具体的类)/接口(){
要重写的方法;
};(2)匿名内部类存在的前提:
要存在一个类或者是一个接口,这个类可以是具体的类也可以是抽象的类interface Inter{ public abstract void show(); public abstract void show2(); } class Outer7{ public void fun(){ //使用匿名内部类的形式创建对象调用show方法 new Inter(){ @Override public void show() { System.out.println("这是show方法"); } @Override public void show2() { System.out.println("这是show2方法"); } }.show(); //使用匿名内部类的形式创建对象调用show2方法 new Inter(){ @Override public void show() { System.out.println("这是show方法"); } @Override public void show2() { System.out.println("这是show2方法"); } }.show2(); System.out.println("======================================"); //想一想,我现在的接口中,只有两个方法,方法的个数比较少,没调用一个方法,都要new一下,并且new之后的内容都是一样的 //如果以后接口中的方法很多的时候,你再用这样的方法,就会很麻烦 //怎么改进呢? //利用接口多态的形式给匿名内部类起名字 Inter inter = new Inter(){ @Override public void show() { System.out.println("这是show方法"); } @Override public void show2() { System.out.println("这是show2方法"); } }; inter.show(); inter.show2(); } } public class InnerClassDemo7 { public static void main(String[] args) { Outer7 outer7 = new Outer7(); outer7.fun(); } }
8、匿名内部类在开发中的使用
interface Person{ public abstract void study(); } class PersonDemo{ Person person; // Person person = new ..(); // PersonDemo(){} PersonDemo(Person person){ // Person person = new Student(); this.person = person; } public void fun(Person person){ person.study(); } } //class Student implements Person{ // @Override // public void study() { // System.out.println("好好学习,天天向上"); // } //} public class InnerClassDemo8 { public static void main(String[] args) { // Student student = new Student(); // //创建一个PersonDemo的对象 // PersonDemo personDemo = new PersonDemo(student); //使用匿名内部类的形式创建对象 Person person = new Person() { @Override public void study() { System.out.println("好好学习,天天向上"); } }; person.study(); //使用匿名内部类进行方法传参 PersonDemo personDemo = new PersonDemo(new Person() { @Override public void study() { System.out.println("这是匿名内部类使用带参构造方法"); } }); new PersonDemo(new Person() { @Override public void study() { System.out.println("这是匿名内部类使用带参构造方法"); } }).fun(new Person() { @Override public void study() { System.out.println("好好学习天天向上2"); } }); new PersonDemo(new Person() { @Override public void study() { System.out.println("这是匿名内部类使用带参构造方法"); } }).person.study(); } }
9、例题:
interface Inter { void show(); }
class Outer { //补齐代码 }
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”interface Inter2{ void show(); } class Outer8{ //1、根据main方法调用的代码推出第一个结论:method()是静态的,可以直接通过类名访问/调用 //2、根据main方法中调用完method()方法之后,还能继续调用方法,我们判定method()是有返回值的 //而再观察后发现,show()方法恰好是Inter2接口中的方法,所以返回值类型是接口Inter2类型 //根据调用method()方法的参数是空,所以判定method()方法没有参数 public static Inter2 method(){ return new Inter2() { @Override public void show() { System.out.println("HelloWorld"); } }; } } public class InnerClassDemo9 { public static void main(String[] args) { Outer8.method().show(); } }