内部类与匿名内部类
内部类
一、内部类概述和访问特点
1.内部类概述:
在一个类中,可以定义其它类,这些类称为内部类。
内部类所在的类称为“外部类”。
2.内部类的访问特点:
内部类可以直接访问外部类的成员和方法,无需受到权限修饰符的限制。
外部类要访问内部类的成员,必须创建对象,通过对象来访问内部类的成员和方法。
例子:
package cm.java.about_innerClass;
public class OuterClass {
/*
*这个类用于展示内部类及内部类与外部类的关系
*/
//定义了三种不同权限修饰符的成员;
private int privateMember;
protected int protectedMember;
public int publicMember;
public OuterClass() {
privateMember = 1;
protectedMember = 2;
publicMember = 3;
}
//定义三种不同权限修饰符的方法;
private void privateFun() {
System.out.println("privateMember:" + privateMember);
}
protected void protectedFun() {
privateFun();
System.out.println("protectedMember:" + protectedMember);
}
public void publicFun() {
privateFun();
System.out.println("publicMember:" + publicMember);
}
/*
*这是OuterClass类的内部类
*/
public class InnerClass {
private int innerMember;
public InnerClass() {
innerMember = 4;
}
//在内部类的方法中,可以直接引用外部类的所有成员与方法,并且,不受权限修饰符的约束;
private void innerFun() {
privateMember++;
protectedMember++;
publicMember++;
privateFun();
protectedFun();
publicFun();
System.out.println("innerMember:" + innerMember);
}
}
//外部类可以定义内部类对象的成员;
private InnerClass innerObject;
public void fun() {
//实例化该成员
innerObject = new InnerClass();
//外部类的方法,可以通过内部类的对象引用内部类的所有成员和方法;
innerObject.innerFun();
System.out.println(innerObject.innerMember);
}
}
二、内部类分类及成员内部类的直接使用
1.按照内部类位置分类
成员位置:在成员位置定义的类,被称为成员内部类。
局部位置:在局部位置定义的类,被称为局部内部类,也就是在方法中定义的类。
2.成员内部类
在测试类中直接访问内部类的成员:
外部类名.内部类名 对象名 = 外部类对象.内部类对象
如:OuterClass.InnerClass 对象名 = new OuterClass().new InnerClass();
三、成员内部类的常见修饰符及应用
1.成员内部类的修饰符:
private :是为了保证数据的安全性
static :是为了方便访问数据
注意事项:
a:静态内部类访问的外部类数据必须用静态修饰。
b: 成员方法可以是静态的也可以是非静态的
2.成员内部类被静态修饰后的访问方式是:
外部类名.内部类名 对象名 = new 外部类名.内部类名(),例:
OuterClass.InnerClass 对象名 = new OuterClass.InnerClass();
四、局部内部类访问局部变量的问题
1.可以直接访问外部类的成员
2. 可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
3.局部内部类访问局部变量必须用final修饰:
因为**局部变量会随着方法的调用完毕而消失**,这个时候,局部对象并没有立马从堆内存中消失,还要使用那
个变量。
为了让数据还能继续被使用,就用fianl修饰,这样,在堆内存里面存储的其实是一个常量值(放在常量池中)。
JDK1.8之后,final会默认加上,因此不用手动去加,但是你要知道其前是存在final修饰的。
例:
public class MyTest3 {
public static void main(String[] args) {
// Outer.Inner outer = new Outer().new Inner();//测试类中直接访问内部类的成员
// 内部类可以用static 修饰 ,修饰之后,创建内部类的语法发生变化
Outer.Inner inner = new Outer.Inner();
// 内部类可以用static 修饰,
//内部类一旦静态修饰后,就只能访问外部类的静态成员
}
}
class Outer {
static int num = 100;
int aa = 200;
//内部类可以用static 修饰
static class Inner {
public void neiShow() {
System.out.println(num);
waiShow();
}
public void neiTest() {
Outer outer = new Outer();
System.out.println(Outer.aa);
}
}
public static void waiShow() {
}
}
五、小练习,看看自己是否已经掌握
要求:使用已知的变量,在控制台输出30,20,10。
class Outer {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(?);//30
System.out.println(?);//20
System.out.println(?); //10
}
}
}
class InnerClassTest {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
答案:
num
this.num
new Outer().num
匿名内部类
一、匿名内部类的格式和理解
1.匿名内部类:就是局部内部类的写法,本质上是一个对象,是谁的对象,是继承了该抽象类,或实现了该接口的匿名子类对象。
2.前提:存在一个类或者接口;这里的类可以是具体类也可以是抽象类。
3.格式:
new 类名或者接口名(){
重写方法;
} ;
二、匿名内部类的方法调用
//不使用匿名内部类的方法调用
public class MyTest2 {
public static void main(String[] args) {
DD dd = new DD();
dd.show();
dd.test();
}
}
interface MyInterface{
void show();
void test();
}
class DD implements MyInterface{
@Override
public void show() {
System.out.println("aaaaaaaaaa");
}
@Override
public void test() {
System.out.println("bbbbbbbbbb");
}
}
//使用匿名内部类的方法调用
public class MyTest2 {
public static void main(String[] args) {
//匿名内部类1
new MyInterface(){
@Override
public void show() {
System.out.println("bbbbbbbbbbbbbbbb");
}
@Override
public void test() {
}
};
//匿名内部类2
new MyInterface() {
@Override
public void show() {
System.out.println("bbbbbb222222222222bbbbbbbbbb");
}
@Override
public void test() {
}
}.show();
}
}
interface MyInterface{
void show();
void test();
}
public class MyTest2 {
public static void main(String[] args) {
//匿名内部类经常用于作为参数传递,或者作为返回值返回
set(new MyClass() {
@Override
public void show() {
System.out.println("aaaaaaaaaaaaaaaaaa");
}
});
MyClass my = new MyClass() {
@Override
public void show() {
System.out.println("aaaaaaaabbbbbbbbbbbbbbbbbbbaaaaaaaaaa");
}
};
set(my);
set2(new WW() {
@Override
public void hehe() {
System.out.println("ccccccccccccccccc");
}
});
WW ww= new WW() {
@Override
public void hehe() {
System.out.println("ccccccccccccccccc");
}
};
set2(ww);
}
public static void set(MyClass myClass){
myClass.show();
}
public static void set2(WW ww) {
ww.hehe();
}
}
abstract class MyClass{
public abstract void show();
}
interface WW{
void hehe();
}
对比后,可以总结出使用匿名内部类的好处:
A.不需要明确地生成派生类,这对于简单问题,明显提高了编程效率;
B.在需要时临时产生匿名内部类,实现抽象方法,这样更灵活;
C.一个匿名内部类对应一种抽象方法的实现,这样更紧凑。
三、匿名内部类中this关键字
interface Inter {
public static final int a = 23 ;
}
public class Test {
public static void main(String[] args) {
new Inter() {
public void show() {
//this 匿名内部类
System.out.println(this.a);//23
System.out.println(Inter.a);//23
}
}.show();
}
}
又次程序可以看出,匿名内部类中的this指的就是new的那个类。