Java内部类详解

Java 内部类

一、概述

java类除了我们常见的,直接定义在java文件中的之外,还有一种定义在类内部的类被称为内部类。内部类包括四种:成员内部类、局部内部类、匿名内部类和静态内部类。

二、成员内部类

成员内部类是最普通的内部类,其定义在另一个类的内部。成员内部类可以定义费静态的属性和方法,不可以定义静态属性和方法,也不可以定义静态代码块,但可以定义static final类型的属性。内部类是外部类的成员,只有当外部类初始化的时候,内部类才会初始化。

内部类的创建

不可以直接使用构造方法创建内部类,只能通过外部类的实例对象来创建内部类

Outer o = new Outer();
Inner i = o.new Inner();

内部类访问外部类

内部类可以直接访问外部类的数据,且不受访问控制符限制,访问时可以直接通过属性名访问,也可以通过外部类.this.属性访问

class Outer{
    public String strOuter = "123";
    class Inner{
        public String strInner = "456"
        public void print(){
            System.Out.Println(strOuter);
            System.Out.Println(Outer.this.strOuter);
        }
    }
}

外部类访问内部类

外部类不可以直接访问内部类的成员,必须先创建一个内部类的实例才能访问,通过创建一个实例,外部类也能访问内部类的私有属性。外部类可以通过内部类的类名直接访问内部类的常量

//外部类的方法
public void printInner(){
    System.out.println(new Inner().strInner);
}

内部类与外部类的冲突

内部类可以拥有与外部类同样的属性名与方法名,当内部类的属性和外部类重名时,内部类可以直接访问自己的属性,但访问外部类的属性则需要使用外部类.this.属性名(或方法)

成员内部类实例

public class Test<T> {
    public static void main(String[] args) {
        Outer o = new Outer();
        Outer.Inner i = o.new Inner();
        o.printInner();
        i.printOuter();
    }
}
class Outer{
    public String strOuter = "123";
    public String str = "abc";
    public void printInner(){
        System.out.println("Outer.printInner");
        System.out.println(str);
        System.out.println(new Inner().str);
        System.out.println(new Inner().strInner);
    }
    public class Inner{
        public String strInner = "456";
        public String str = "def";
        public void printOuter(){
            System.out.println("Inner.printOuter");
            System.out.println(str);
            System.out.println(Outer.this.str);
            System.out.println(strOuter);
        }
    }
}

运行结果:

Outer.printInner
abc
def
456
Inner.printOuter
def
abc
123

三、局部内部类

局部内部类简单点说就是在一个外部类的成员方法中定义的类。局部内部类不允许使用任何访问修饰符修饰,只在方法体中有效,在外部类中也不能创建一个局部内部类的实例,也不能访问局部内部类,只能在定义内部类的方法体中访问。局部内部类中不能包含static成员,但可以包含final static成员。局部内部类可以嵌套。

局部内部类访问外部类

局部内部类可以访问外部类中的所有成员,不受访问控制符的限制。

class Outer{            
    String id = "Outer";
    public void fun(){
        class Inner{
            String outer = id;
            public void fun2(){
                System.out.println(outer);
            }
        }
        Inner inner = new Inner();
        inner.fun2();
    }
}

调用fun后输出为Outer

命名冲突

如果内部类的成员或方法与外部类的同名,那么在内部类中直接使用该属性时默认访问内部类的属性,若需要访问外部类的属性则须使用外部类.this.属性名

class Outer{
    String id = "Outer";
    public void fun(){
        class Inner{
            String id = "Inner";
            public void print(){
                System.out.println(id);
                System.out.println(Outer.this.id);
            }
        }
        Inner inner = new Inner();
        System.out.println(id);
        System.out.println(inner.id);
        inner.print();
    }
}
Outer
Inner
Inner
Outer

四、匿名内部类

简单说匿名内部类就是没有名字的类,既然没有名称,也就意味着不能再其他地方引用,不能实例化,没有构造器,因而只能使用一次。匿名内部类的属性和方法都不能是static匿名内部类可以访问外部类的成员变量和方法。在写事件监听器的时候经常会使用匿名内部类

匿名内部类创建与使用

匿名内部类必须在存在继承或实现的情况下使用。

//继承于抽象类的匿名内部类
abstract class person{
    String career;
}
class Outer{
    public void fun(){
        new person(){
            public void printCareer(){
                career = "学生";
                System.out.println(career);
            }
        }.printCareer();
    }
}
interface person{public void printCareer();}
class Outer{
    public void fun(){
        new person(){
            public void printCareer(){
                String career = "学生";
                System.out.println(career);
            }
        }.printCareer();
    }
}

这是最简单的只有一个方法的匿名内部类,那么如果我们要调用匿名内部类的多个方法呢?第一种方法时利用多态,但是必须要保证父类或接口中已经声明了要调用的方法

abstract class person{
    String career;
    public abstract void setCareer();
    public abstract void printCareer();
}
class Outer{
    public void fun(){
        person student = new person(){
            public void setCareer(){
                career = "学生";
            }
            public void printCareer(){
                System.out.println(career);
            }
        };
        student.setCareer();
        student.printCareer();
    }
}

第二种方法是将父类的方法返回类型改为this,这样就可以直接调用多个方法

abstract class person{
    String career;
    public abstract person setCareer();
    public abstract person printCareer();
}
class Outer{
    public void fun(){
        new person(){
            public person setCareer(){
                career = "学生";
                return this;
            }
            public person printCareer(){
                System.out.println(career);
                return this;
            }
        }.setCareer().printCareer();
    }
}

五、静态内部类

用static关键词修饰的内部类即为静态内部类,其和类属性一样,属于外部类本身,而不属于外部类的任何一个对象。静态内部类中可以包含静态成员也可以包含费静态成员,但在非静态内部类中不可以声明静态成员。静态内部类只可以访问外部类的类属性,不可以访问外部类的实例属性。外部类不可以为静态类。

静态内部类的创建与使用

public class Test<T> {
    public static void main(String[] args) {
        Outer.inner inner = new Outer.inner();
        inner.print();
    }
}

class Outer{
    public static class inner{
        String id = "Inner";
        public void print(){
            System.out.println(id);
        }
    }
}

输出Inner

六、内部类的优点

1、每个内部类都都可以独立实现一个接口,因此无论外部类是否实现了某个接口,都不影响内部类对接口的实现,使得多继承的解决方案变得完整

2、便于将存在一定关系的类组织在一起,且能对外界隐藏实现

3、便于事件驱动程序的实现

4、便于多线程的编写

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值