一、内部类和匿名内部类:
1、内部类:
Java中的内部类是指在一个类的内部定义的另一个类。内部类可以访问外部类的成员变量和方法,而外部类不能访问内部类的成员变量和方法。Java中的内部类分为四种类型:成员内部类、静态内部类、局部内部类和匿名内部类
(1)成员内部类:
成员内部类是定义在类的内部,且不是static修饰的内部类。成员内部类可以访问外部类的成员变量和方法,而外部类也可以访问成员内部类的成员变量和方法
public class Outer {
private int x = 10;
public class Inner {
public void printX() {
System.out.println(x);
}
}
}
成员内部类的特点:
1、成员内部类可以直接访问外部类的成员,包括私有的,也可以通过外部类名.this.成员名调用外部成员。
2、外部类访问非静态成员内部类的成员,必须要创建成员内部类对象;外部类可以通过类名直接访问静态内部类的静态成员,包括私有的。
3、成员内部类和外部类不存在继承关系
4、其他类中生成成员内部类的方式:Outer.Inner oi = new Outer().new Inner();
访问特点:
内部类可以直接访问外部类的成员,包括私有成员。外部类要访问内部类的成员,必须要建立内部类的对象。创建内部类对象格式:
外部类名.内部类名 对象名 = new 外部类().new 内部类();
示例:
public class Person {
private boolean live = true;
class Heart{//内部类
public void jump(){
//直接访问外部类的私有成员live
if(live){
System.out.println("心里还有你,勇敢点");
}
else{
System.out.println("心里没你了,放下吧");
}
}
}
public boolean isLive(){
return live;
}
public void setLive(boolean live){
this.live = live;
}
}
public class InnerDemo {
public static void main(String[] args){
//创建外部类对象
Person p = new Person();
//创建内部类对象
Person.Heart heart = p.new Heart();
//调用内部类方法
heart.jump();
//调用外部类方法
p.setLive(false);
//调用内部类方法
heart.jump();
}
}
结果:
(2)静态内部类:
静态内部类是定义在类的内部,且被static修饰的内部类。静态内部类不能访问外部类的非静态成员变量和方法,只能访问外部类的静态成员变量和方法。
public class Outer {
private static int x = 10;
public static class Inner {
public void printX() {
System.out.println(x);
}
}
}
静态内部类的特点:
1、在创建静态内部类的实例时,不需要创建外部类的实例。
2、静态内部类中可以定义静态成员和实例成员。外部类以外的其他类需要通过完整的类名访问静态内部类中的静态成员,如果要访问静态内部类中的实例成员,则需要通过静态内部类的实例。
3、静态内部类可以直接访问外部类的静态成员,如果要访问外部类的实例成员,则需要通过外部类的实例去访问。
示例:
public class Static {
int a0 = 1;//实例变量
static int b0 = 1;//静态变量
static class Inner{
int a = 0;//实例变量
static int b = 0;//静态变量
Static s = new Static();
int a2 = s.a0;//访问实例变量
static int b2 = b0;//访问静态变量
}
}
public class Test {
public static void main(String[] args){
Static.Inner oi = new Static.Inner();
int a1 = oi.a2;//访问实例成员
int b1 = Static.Inner.b2;//访问静态成员
System.out.println("a1 = " + a1);
System.out.println("b1 = " + b1);
}
}
结果:
(3)局部内部类
局部内部类是定义在方法内部的类。局部内部类只能在定义它的方法内部使用,不能在方法外部使用。
public class Outer {
public void print() {
class Inner {
public void printX() {
System.out.println("Inner class");
}
}
Inner inner = new Inner();
inner.printX();
}
局部内部类的特点:
1、局部内部类与局部变量一样,不能使用访问控制修饰符(public、private 和 protected)和 static 修饰符修饰。
2、局部内部类只在当前方法中有效。
3、局部内部类中不能定义 static 成员。
4、局部内部类中还可以包含内部类,但是这些内部类也不能使用访问控制修饰符(public、private 和 protected)和 static 修饰符修饰。
5、在局部内部类中可以访问外部类的所有成员。
6、在局部内部类中只可以访问当前方法中 final 类型的参数与变量。如果方法中的成员与外部类中的成员同名,则可以使用 <OuterClassName>.this.<MemberName> 的形式访问外部类中的成员。
示例:
public class Test {
int a = 0;
int d = 0;
public void method(){
int b = 0;
final int c = 0;
final int d = 10;
class Inner{
int a2 = a;
int c2 = c;
int d2 = d;
int d3 = Test.this.d;
}
Inner i = new Inner();
System.out.println("d2 = " + i.d2);
System.out.println("d3 = " + i.d3);
}
public static void main(String[] args){
Test t =new Test();
t.method();
}
}
结果:
(4)匿名内部类
匿名内部类是没有名字的内部类。匿名内部类通常用于创建实现某个接口或继承某个类的对象。
public class Outer {
public void print() {
Outer out = new Runnable() {
public void run() {
System.out.println("Thread is running");
}
}
}
匿名内部类的特点:
(1)匿名类和局部内部类一样,可以访问外部类的所有成员。
(2)匿名类中允许使用非静态代码块进行成员初始化操作。
(3)匿名类的非静态代码块会在父类的构造方法之后被执行。
注意:
匿名内部类在创建对象的时候只能使用一次;如果希望多次创建对象,而且类的内容一样,那么就必须使用单独定义的实现类了。
匿名对象(也就是没有接口名 对象名 = )在调用方法的时候,只能调用一次,如果想要多次调用,就必须接口名 对象名 = new 接口名(){};写完整
示例一:
//普通类的匿名内部类
public class Out {
public Out(){
System.out.println("Out类的无参构造方法" );
}
public Out(int i ){
System.out.println("Out类中的有参构造方法");
}
void show(){
System.out.println("调用Out类的无参show()方法");
}
void show(int j){
System.out.println("调用Out类中的有参show()方法");
}
}
//抽象类的匿名内部类
public abstract class Abstract {
public abstract void show();
}
public class Inter {
private void show(){
//在这个方法中构造一个匿名内部类
Out annyInter = new Out(){
//获取匿名内部类的实例,对Out类中的show()方法覆盖重写
@Override
void show(){
System.out.println("调用匿名类中的无参show()方法");
}
@Override
void show(int j){
System.out.println("调用匿名类中的有参show()方法");
}
};
annyInter.show();
annyInter.show(1);
}
public static void main(String[] args){
Inter test = new Inter();
test.show();
System.out.println("----------------");
//在main方法中构造关于Out的多个匿名内部类
int a = 0;
final int b = 10;
Out annoy = new Out(1){
@Override
void show(){
System.out.println("调用匿名类中的无参show()方法" + a);
System.out.println("调用匿名类中的s无参how()方法" + b);
}
};
annoy.show();
System.out.println("----------------");
/**
1.等号右边:是匿名内部类,定义并创建该接口的子类对象
2.等号左边:是多态赋值,接口类型引用指向子类对象
*/
Out ann = new Out(){
int i;{//非静态代码块
i = 10;//成员初始化
}
@Override
public void show(){
System.out.println("调用匿名类中的无参show()方法" + i);
}
};
ann.show();
System.out.println("----------------");
//匿名内部类:在实例化对抽象类的同时并重写抽象方法
new Abstract() {
@Override
public void show(){
System.out.println("重写了抽象类的show()方法");
}
}.show();
}
}
运行结果: