内部类概述:
把类定义在其他类的内部,我们称之为内部类。
内部类的特点:
1、内部类可以访问外部类的成员,包括私有的;
2、外部类想要访问内部类的成员,必须要创建内部类的对象;
package com.one;
class Outer1{
private int num=10;
class Inner1{
public void show(){
System.out.println(num);
}
}
public void fun(){
Inner1 inner1=new Inner1();
inner1.show();
}
}
public class InnerClass1 {
public static void main(String[] args) {
Outer1 outer1=new Outer1();
outer1.fun();
// 10
}
}
按照内部类在类中定义的位置不同,可以分为如下两种格式:
成员位置(成员内部类)
局部位置(局部内部类)
class Outer2{
//定义在成员的位置上(成员内部类)
class Inner2{
}
public void fun(){
//定义在局部范围内(局部内部类)
class Inner3{
}
}
}
成员内部类:
1、定义在类的成员位置上;
2、内部类可以访问外部类的成员,包括私有的;
package com.one;
class Outer2{
private int num=10;
class Inner2{
public void show(){
System.out.println(num);
}
}
}
public class InnerClass2 {
public static void main(String[] args) {
// 访问Inner中show方法
// 正确创建成员内部类对象的格式
// 外部类名.成员内部类名 对象名 = new 外部类名().new 成员内部类名();
Outer2.Inner2 a=new Outer2().new Inner2();
a.show();
}
}
成员内部类常见的修饰符:
privatw:其他类不能直接访问内部类的对象,要想使用被private修饰的成员,必须在本类中间接的创建对象调用;
static:内部类如果是被static修饰的时候,只能访问外部类中的静态成员;
package com.one;
class Outer3{
private static int num=10;
static class Inner3{
public static void fun(){
System.out.println(num);
}
}
}
public class InnerClass3 {
public static void main(String[] args) {
// 当内部类是被静态所修饰的时候,出现了另外一种创建内部类的方式
//格式如下:
//外部类名.内部类名 对象名 = new 外部类名.内部类名();
// Outer4.Inner4 oi4 = new Outer4.Inner4();
// oi4.fun();
//直接通过类名直接调用
Outer3.Inner3.fun();
// 10
}
}
尝试从控制台输出:30、20、10
package com.one;
class Outer4{
public int num=10;
class Inner4{
public int num=20;
public void show(){
int num=30;
System.out.println(num);
// 30
System.out.println(this.num);
// 20
System.out.println(Outer4.this.num);
// 10
}
}
}
public class InnerClass4 {
public static void main(String[] args) {
Outer4.Inner4 a=new Outer4().new Inner4();
a.show();
}
}
局部内部类:
1、定义在方法中的类;
2、局部内部类可以直接访问外部类中的所有成员;
3、想要使用局部内部类的方法,在定义局部内部类的成员方法中,创建局部内部类的调用方法;
在局部类中引用的本地变量必须是最终变量或者是实际上的最终变量;
package com.one;
class Outer5{
public int num1=10;
public void show(){
int num2=20;
class Inner5{
int num3=30;
public void fun(){
//在局部内部类中引用的本地的变量必须是最终变量或者实际上的最终变量
//通过反编译工具观察发现,存在局部内部类的方法中定义的局部变量自动加上了final关键字
//在JDK1.8之后会自动加上final关键字 num2=30;
System.out.println(num1);
System.out.println(num2);
System.out.println(num3);
}
}
Inner5 a=new Inner5();
a.fun();
}
}
public class InnerClass5 {
public static void main(String[] args) {
Outer5 b=new Outer5();
b.show();
}
}
匿名内部类:
语句定义格式:
new 类名(可以是抽象类也可以是具体类)/接口(){
重写的方法;
};
案例
interface A{ b(); c(); } class B implements A{ b(){...}; c(){...}; } A a = new B(); a.b(); a.c();
通过匿名内部类改进后
A a = new A(){ b(){...} c(){...} };
package com.one;
interface Inter6{
public void show1();
public void show2();
}
//正常步骤
//class B implements Inter{
//
// @Override
// public void show() {
//
// }
//
// @Override
// public void show2() {
//
// }
//}
//Inter i = new B()
class Outer6 {
public void fun() {
//使用匿名内部类的形式创建对象调用show1方法
new Inter6() {
@Override
public void show1() {
System.out.println("这是show1方法");
}
@Override
public void show2() {
System.out.println("这是show2方法");
}
}.show1();
//使用匿名内部类的形式创建对象调用show2方法
new Inter6() {
@Override
public void show1() {
System.out.println("这是show1方法");
}
@Override
public void show2() {
System.out.println("这是show2方法");
}
}.show2();
System.out.println("========================================");
//想一想,我现在的接口中,只有两个方法,方法的个数比较少,没调用一个方法,都要new一下,并且new之后的内容都是一样的
//如果以后接口中的方法很多的时候,你再用这样的方法,就会很麻烦
//怎么改进呢?
//利用接口多态的形式给匿名内部类起名字
Inter6 inter6=new Inter6() {
@Override
public void show1() {
System.out.println("这是show1方法");
}
@Override
public void show2() {
System.out.println("这是show2方法");
}
};
inter6.show1();
inter6.show2();
}
}
public class InnerClass6 {
public static void main(String[] args) {
Outer6 outer6=new Outer6();
outer6.fun();
}
}
//运行结果
// 这是show1方法
//这是show2方法
//========================================
//这是show1方法
//这是show2方法
匿名内部类在开发中的使用:
package com.one;
interface Human{
public abstract void study();
}
class HumanDemo{
Human human;
HumanDemo(Human human){this.human=human;}
public void fun(Human human){human.study();}
}
public class InnerClass7 {
public static void main(String[] args) {
Human human=new Human() {
@Override
public void study() {
System.out.println("好好学习,天天向上");
}
};
human.study();
// 好好学习,天天向上
HumanDemo humanDemo=new HumanDemo(new Human() {
@Override
public void study() {
System.out.println("这是匿名内部类使用带参构造方法");
}
});
new HumanDemo(new Human() {
@Override
public void study() {
System.out.println("这是匿名内部类使用带参构造方法");
}
}).fun(new Human() {
@Override
public void study() {
System.out.println("好好学习,天天向上1");
}
});
// 好好学习,天天向上1
new HumanDemo(new Human() {
@Override
public void study() {
System.out.println("这是匿名内部类使用带参构造方法");
}
}).human.study();
// 这是匿名内部类使用带参构造方法
}}
尝试补齐代码:
/*
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 Inter();
// Student student = new Student();
// return student;
return new Inter2() {
@Override
public void show() {
System.out.println("HelloWorld");
}
};
}
}
//class Student implements Inter2{
// @Override
// public void show() {
// System.out.println("HelloWorld");
// }
//}
public class InnerClassDemo9 {
public static void main(String[] args) {
Outer8.method().show();
}
}