• Java内部类用法


    内部类可以是静态(static)的,可以使用 public、protected 和 private 访问控制符,而外部类只能使用 public,或者默认。

    成员式内部类

    在外部类内部直接定义(不在方法内部或代码块内部)的类就是成员式内部类,它可以直接使用外部类的所有变量和方法,即使是 private 的。外部类要想访问内部类的成员变量和方法,则需要通过内部类的对象来获取。

     1 public class Outer{
     2 private int size;
     3 public class Inner {
     4 public void dostuff() {
     5 size++;
     6 }
     7 }
     8 public void testTheInner() {
     9 Inner in = new Inner();
    10 in.dostuff();
    11 }
    12 }

    成员式内部类如同外部类的一个普通成员。

    成员式内部类可以使用各种修饰符,包括 public、protected、private、static、final 和 abstract,也可以不写。

    若有 static 修饰符,就为类级,否则为对象级。类级可以通过外部类直接访问,对象级需要先生成外部的对象后才能访问。

    非静态内部类中不能声明任何 static 成员。

    内部类可以相互调用,例如:

    1 class A {
    2 // B、C 间可以互相调用
    3 class B {}
    4 class C {}
    5 }

    成员式内部类的访问

    内部类的对象以成员变量的方式记录其所依赖的外层类对象的引用,因而可以找到该外层类对象并访问其成员。该成员变量是系统自动为非 static 的内部类添加的,名称约定为“outClassName.this”。

    1) 使用内部类中定义的非静态变量和方法时,要先创建外部类的对象,再由“outObjectName.new”操作符创建内部类的对象,再调用内部类的方法,如下所示:

     1 public class Demo{
     2 public static void main(String[] args) {
     3 Outer outer = new Outer();
     4 Outer.Inner inner = outer.new Inner();
     5 inner.dostuff();
     6 }
     7 }
     8 class Outer{
     9 private int size;
    10 class Inner{
    11 public void dostuff() {
    12 size++;
    13 }
    14 }
    15 }

    2) static 内部类相当于其外部类的 static 成员,它的对象与外部类对象间不存在依赖关系,因此可直接创建。示例如下:

     1 public class Demo{
     2 public static void main(String[] args) {
     3 Outer.Inner inner = new Outer.Inner();
     4 inner.dostuff();
     5 }
     6 }
     7 class Outer{
     8 private static int size;
     9 static class Inner {
    10 public void dostuff() {
    11 size++;
    12 System.out.println("size=" + size);
    13 }
    14 }
    15 }

    运行结果:
    size=1

    3) 由于内部类可以直接访问其外部类的成分,因此当内部类与其外部类中存在同名属性或方法时,也将导致命名冲突。所以在多层调用时要指明,如下所示:

     1 public class Outer{
     2 private int size;
     3 public class Inner{
     4 private int size;
     5 public void dostuff(int size){
     6 size++; // 局部变量 size;
     7 this.size; // 内部类的 size
     8 Outer.this.size++; // 外部类的 size
     9 }
    10 }
    11 }

    局部内部类

    局部内部类(Local class)是定义在代码块中的类。它们只在定义它们的代码块中是可见的。

    局部类有几个重要特性:

      1. 仅在定义了它们的代码块中是可见的;
      2. 可以使用定义它们的代码块中的任何局部 final 变量;
      3. 局部类不可以是 static 的,里边也不能定义 static 成员;
      4. 局部类不可以用 public、private、protected 修饰,只能使用缺省的;
      5. 局部类可以是 abstract 的。
     1 public class Outer {
     2 public static final int TOTAL_NUMBER = 5;
     3 public int id = 123;
     4 public void func() {
     5 final int age = 15;
     6 String str = "http://www.weixueyuan.net";
     7 class Inner {
     8 public void innerTest() {
     9 System.out.println(TOTAL_NUMBER);
    10 System.out.println(id);
    11 // System.out.println(str);不合法,只能访问本地方法的final变量
    12 System.out.println(age);
    13 }
    14 }
    15 new Inner().innerTest();
    16 }
    17 public static void main(String[] args) {
    18 Outer outer = new Outer();
    19 outer.func();
    20 }
    21 }

    运行结果:
    5
    123
    15

    匿名内部类

    匿名内部类是局部内部类的一种特殊形式,也就是没有变量名指向这个类的实例,而且具体的类实现会写在这个内部类里面。

    注意:匿名类必须继承一个父类或实现一个接口。

    不使用匿名内部类来实现抽象方法:

     1 abstract class Person {
     2 public abstract void eat();
     3 }
     4 class Child extends Person {
     5 public void eat() {
     6 System.out.println("eat something");
     7 }
     8 }
     9 public class Demo {
    10 public static void main(String[] args) {
    11 Person p = new Child();
    12 p.eat();
    13 }
    14 }

    运行结果:
    eat something

    可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用。但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦?

    这个时候就引入了匿名内部类。使用匿名内部类实现:

     1 abstract class Person {
     2 public abstract void eat();
     3 }
     4 public class Demo {
     5 public static void main(String[] args){
     6 // 继承 Person 类
     7 new Person() {
     8 public void eat() {
     9 System.out.println("eat something");
    10 }
    11 }.eat();
    12 }
    13 }

    可以看到,匿名类继承了 Person 类并在大括号中实现了抽象类的方法。

    内部类的语法比较复杂,实际开发中也较少用到,也不应该将内部类作为学习Java的重点。 
  • 相关阅读:
    MySQL常用函数及逻辑运算
    博客主题2
    TCPIP详解第1卷1.3TCPIP分层1.4互联网的地址1.5域名系统1.6封装
    删除数组中满足特定需求的数字
    自定义简洁浏览器主页
    Matlab图像处理函数:regionprops
    连通域的质心
    Matlab的GUI参数传递方式总结
    retrifit
    association ,collection
  • 原文地址:https://www.cnblogs.com/chenglc/p/6922760.html
Copyright © 2020-2023  润新知