内部类
将一个类定义在另一类的内部,这就是内部类。
1. 内部类的访问规则
/*
内部类的访问规则:
1、内部类可以直接访问外围类中的成员,包括私有。
之所以可以直接访问外围类的成员,是因为内部类持有了一个外围类的引用。
格式:外围类名.this。
2、外围类要访问内部类,必须建立内部类对象。
3、如果想从外部类的非静态方法之外的任意位置创建某个内部类的对象,那么必须具体指明这个对象的类型:OuterClassName.InnerClassName。
*/
class Outer{
private int x = 5;
void method(){
Inner in = new Inner(); //外围类要访问内部类,必须建立内部类对象。
in.function();
}
class Inner{ //内部类。
//private int x = 2;
void function(){
//int x = 7;
System.out.println("inner:"+Outer.this.x);//内部类可以直接访问外围类中的成员,包括私有。
}
}
}
class InnerClassDemo{
public static void main(String[] args){
Outer out = new Outer();
out.method();
//直接访问内部类中的成员。
Outer.Inner in = new Outer().new Inner();//当内部类被private修饰时,就不可以使用这种方式访问。
in.function();
}
}
2.静态内部类
/*
访问格式
1、当内部类定义在外围类的成员位置上,
而且非私有,可以在外部其他类中直接建立内部类对象。
格式:
外围类名.内部类名 变量名 = 外围类对象.内部类对象;
Outer.Inner in = new Outer().new Inner();
2、当内部类在成员位置上,就可以被成员修饰符所修饰。
比如,private:将内部类在外围类中进行封装。
static:内部类就具备static的特性。
当内部类被static修饰后,只能直接访问外围类中的static成员。出现了访问局限。
在外部其他类中,如何直接访问static内部类的非静态成员呢?
new Outer.Inner().function();
在外部其他类中,如果直接访问static内部类的静态成员呢?
Outer.Inner.show();
注意:当内部类中定义了静态成员,该内部类必须是static的。
当外围类中的静态方法访问内部类时,内部类也必须是static的。
*/
class Outer{
private int x = 5;
void method(){
Inner in = new Inner(); //外围类要访问内部类,必须建立内部类对象。
in.function();
}
class Inner{ //内部类。
//private int x = 2;
void function(){
//int x = 7;
System.out.println("inner:"+Outer.this.x);//内部类可以直接访问外围类中的成员,包括私有。
}
}
}
class InnerClassDemo{
public static void main(String[] args){
Outer out = new Outer();
out.method();
//直接访问内部类中的成员。
Outer.Inner in = new Outer().new Inner();//当内部类被private修饰时,就不可以使用这种方式访问。
in.function();
}
}
3.在方法和作用域中定义内部类(内部类定义在局部)
/*
内部类定义在局部:
1、 不可以被成员修饰符修饰。
2、 可以直接访问外围类中的成员,因为还持有外围类中的引用。
但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量。(即如果变量在内部类内部被直接使用,该变量必须是final的)。
3、不会因为作用域的结束而消失
*/
class Outer{
int x = 3;
void method(final int a){
class Inner{
final int y = 4;
void function(){
System.out.println(y); //变量在内部类内部被直接使用,必须是final的
System.out.println(a); //变量在内部类内部被直接使用,必须是final的
}
}
}
new Inner().function();
}
class InnerClassDemo{
public static void main(String[] args){
new Outer().method(7);
}
}
4.匿名内部类
/*
匿名内部类:
1、 匿名内部类其实就是内部类的简写格式。
2、 定义匿名内部类的前提:
a) 匿名内部类必须是继承一个类或实现接口
b) 匿名内部类可以继承一个类或实现接口,但不能继承一个类的同时实现接口,而且如果实现接口,也只能实现一个接口,不能实现多个。
3、 匿名内部类的格式: new 父类或者接口(){定义子类的内容}
4、 其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。可以理解为带内容的对象。
5、 匿名内部类中定义的方法最好不要超过3个。
*/
abstract class AbsDemo{
abstract void show();
}
class Outer{
int x = 3;
/*
class Inner extends AbsDemo{ //这个是不用匿名内部类的写法。
int num = 9;
void show(){
System.out.println(x);
}
void abc(){
System.out.println("haha");
}
}
*/
public void function(){
//new Inner().show(); //这个是用匿名内部类的写法。
AbsDemo a = new AbsDemo(){ //注意这个括号的写法
int num = 9;
void show(){
System.out.println(x);
}
void abc(){
System.out.println("haha");
}
};
a.show();
//a.abc(); //编译失败,因为在父类中不存在该方法
}
}
class InnerClassDemo{
public static void main(String[] args){
new Outer().function();
}
}
5.匿名内部类创建一个构造器的效果
在匿名内部类中不可能有命名构造器(因为它根本没名字!),但通过实例初始化,就能够达到为匿名内部类创建一个构造器的效果。
abstract class Base{
public Base(int i){
System.out.println("base:"+i);
}
public abstract void method();
}
public class AnonymousConstructor{
public static Base getBase(int i){ //变量i没有在内部类内部使用,不需为final
return new Base(i){
public void method(){
System.out.println("haha");
//System.out.println(i);//如果在内部类内部使用变量,必须为final
}
};
}
public static void main(String[] args){
Base b = getBase(55);
b.method();
}
}
6.使用内部类实现多继承的效果
每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
使用内部类实现多继承的效果,如果拥有的是抽象类或具体类,而不是接口,那就只能使用内部类实现多继承的效果。
class D{}
abstract class E{}
class Z extends D{
E makeE(){
return new E(){};
}
}
public class MultiImplmentation{
static void takesD(D d){}
static void tatesE(E e){}
public static void main(String[] args){
Z z = new Z();
takesD(z);
takesE(z.makeE());
}
}