浅谈java内部类

一、什么是内部类?

  到底什么是内部类呢?通俗的讲,就是在类内部定义的类,包括定义在一个类的方法外面、方法里面或者代码块中。

二、为什么要使用内部类?

  为什么我们要不走寻常路,把一个类定义在另一个类的内部呢?这样到底是出于什么目的呢?其实内部类是为了弥补java的单继承的特点,以实现多继承。内部类可以继承抽象类或实现接口。这样外部类也继承一个父类,就变相的实现了多继承。内部类可以访问外部类的属性,包括私有属性。

三、成员内部类

  先上代码:

package noStaticInnerClass;

public class OuterClass {

    private int outerPrivateParam = 1;

    public int outerPublicParam = 2;

    public static int outerStaticParam = 3;

    void outerFun()
    {
        System.out.println("function in outer class.");
    }

    public class InnerClass {

        public int innerParam = 4;

        //在非静态内部类中不可以定义静态变量,以下会报编译错
        //public static innerStaticParam = 5;
        public void innerFun() {
            System.out.println("outerPrivateParam : " + outerPrivateParam
                    + ", outerPublicParam : " + outerPublicParam
                    + ", outerStaticParam : " + outerStaticParam);
            //访问外部类的方法
            outerFun();
        }
    }

    public void test()
    {
        InnerClass inner = new InnerClass();
        inner.innerFun();
    }

    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        outer.test();
    }
}

  成员内部类是一种个Field、方法、构造器和初始化块相似的类成员。
  成员内部类又被称为非静态内部类,它具有以下几个特性:

    • 在非静态内部类里可以直接访问外部类的成员。这是因为在非静态内部类对象里,保存了一个它寄存的外部类对象的引用。但是需要注意的是,外部类对象则不一定有非静态内部类对象寄存在其中。
    • 在外部类中不能直接访问内部类的成员,必须通过创建内部类对象来访问。
    • 在非静态内部类对象中不能定义静态方法、静态Field以及静态初始化块。不允许在外部类的静态方法或者静态代码块中直接使用非静态内部类。看下面代码:

package noStaticInnerClass;

public class OuterClass {

    private int outerPrivateParam = 1;

    public int outerPublicParam = 2;

    public static int outerStaticParam = 3;

    public class InnerClass {

        public int innerParam = 4;

        //在非静态内部类中不可以定义静态变量,以下会报编译错
        //public static innerStaticParam = 5;
        public void innerFun() {
            System.out.println("outerPrivateParam : " + outerPrivateParam
                    + ", outerPublicParam : " + outerPublicParam
                    + ", outerStaticParam : " + outerStaticParam);
        }
    }

    public static void test()
    {
        //不可以在外部类的静态方法中直接创建内部类对象
        //InnerClass inner = new InnerClass();
        OuterClass out = new OuterClass();
        InnerClass inner = out.new InnerClass();
        inner.innerFun();
    }
}

这是因为静态方法是类相关的,test方法不需要创建外部类的实例,就可以通过OuterClass.test()来调用,但是非静态内部类对象是依赖外部类的实例对象才能创建的,所以要先显式创建外部类对象。

     非静态内部类的上一级是外部类,所以非静态内部类可以用private、protected、public以及默认修饰符来修饰内部类。如何在外部类以外的部分创建内部类对象呢?

   外部类 外部类实例名 = new 外部类();

   外部类.内部类  内部类实例名 = 外部类实例名.new 内部类();

四、静态内部类

  继续看代码:

  

package noStaticInnerClass;

public class OuterClass {

    private int outerPrivateParam = 1;

    public int outerPublicParam = 2;

    public static int outerStaticParam = 3;

    void outerFun()
    {
        //外部类可以通过内部类.静态成员来访问内部类的静态成员
        System.out.println(InnerClass.innerStaticParam);
    }

    static void outerStaticFun()
    {
        InnerClass.innerStaticFun();
    }
    public static class InnerClass {

        public static int innerStaticParam = 5;
        public int innerParam = 4;

        public void innerFun()
        {
            //在静态内部类中不能访问外部类的非静态成员,以下会报编译错。
            //System.out.println("outerPrivateParam : " + outerPrivateParam);
            //ouerFun();
            System.out.println("outerStaticParam : " + outerStaticParam);
            outerStaticFun();
        }

        public static void innerStaticFun()
        {
            System.out.println(innerStaticParam);
        }
    }    public void test()    {        InnerClass inner = new InnerClass();        System.out.println(inner.innerParam);    }
    public static void main(String[] args) {
        OuterClass.InnerClass inner = new OuterClass.InnerClass();
        inner.innerFun();
        OuterClass.InnerClass.innerStaticFun();
    }
}
  • 静态内部类属于类本身,不需要先创建外部类对象,再来创建内部类对象。
  • 静态内部类只能访问外部类的类成员。
  • 外部类不能直接访问静态内部类中的成员,可以通过创建对象或用类名来访问。

五、局部内部类

  局部内部类放在方法中定义,局部内部类仅在方法内有效。局部类不能使用访问控制修饰符和static修饰符来修饰。

  若需要用局部内部类来创建实例或派生子类,那么只能在局部内部类所在的方法或代码块内进行。

  

package noStaticInnerClass;

public class OuterClass {

    private int outerPrivateParam = 1;

    public int outerPublicParam = 2;

    public static int outerStaticParam = 3;

    void outerFun()
    {
         class InnerClass {

            public int innerParam = 4;

            public void innerFun()
            {
                System.out.println("outerPrivateParam : " + outerPrivateParam
                        + ", outerPublicParam : " + outerPublicParam
                        + ",outerStaticParam : " + outerStaticParam);
            }
        }
        InnerClass inner = new InnerClass();
        inner.innerFun();
        System.out.println(inner.innerParam);
    }

    public static void main(String[] args) {
        OuterClass out = new OuterClass();
        out.outerFun();
    }
}

我们查看以上代码生成的class文件,发现内部类的class文件名中多了一个1,那是因为同一个类中可能有两个以上同名的局部内部类。它们在不同的方法中定义。

  

六、匿名内部类

  适合创建只需要一次使用的类。

  格式 :

      new 父类构造器(实参列表) | 实现接口()

      {

        //匿名内部类的类体部分。

      }

  代码如下 :

package innerClass;

public class OutterClass {

    public TestInterface getInnerClass()
    {
        return new TestInterface() {

            @Override
            public void print(String name) {
                System.out.println(name);
            };
        };
    }

    public static void main(String[] args) {
        OutterClass out = new OutterClass();
        out.getInnerClass().print("demo");
    }
}

创建匿名内部类时会立即创建一个类的实例,这个类定义会立即消失。

匿名内部类必须继承一个父类,或实现一个接口。

   注意 :

  1. 匿名内部类不能是抽象类。
  2. 无法定义构造器,因为匿名内部类没有类名。但可定义初始化完成构造器的功能。          
package innerClass;

public class OutterClass {
    public TestInterface getInnerClass(final String sex)
    {
        final int age = 23;
        return new TestInterface() {

            @Override
            public void print(String name) {
                System.out.println(name + " is a " + sex + " and age is " + age);
            };
        };
    }

    public static void main(String[] args) {
        OutterClass out = new OutterClass();
        out.getInnerClass("boy").print("demo");
    }
}

  如果匿名内部类要访问外部类的局部变量,则必须使用final修饰符来修饰外部类的局部变量。否则编译部通过。

因为这里是拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变。

时间: 2024-10-12 19:56:23

浅谈java内部类的相关文章

浅谈 Java Printing

浅谈 Java  Printing 其实怎么说呢?在写这篇博文之前,我对java printing 可以说是一无所知的.以至于我在敲文字时, 基本上是看着api文档翻译过来的.这虽然看起来非常的吃力,但是我相信,有道大哥不会辜负我的.嘻 嘻! Java Printing 技术,也就是我们平时所接触的打印,只不过是说可以用Java实现而已. 一.Java Printing 打印简介 Java Printing API能够使java应用程序实现相关的打印功能,如: 1.打印所有 Java 2D 和

【转】浅谈Java中的equals和==

浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str2 = new String("hello"); 3 4 System.out.println(str1==str2); 5 System.out.println(str1.equals(str2)); 为什么第4行和第5行的输出结果不一样?==和equals方法之间的区别是什么?如果在初

浅谈java异常[Exception]

本文转自:focusJ 一. 异常的定义 在<java编程思想>中这样定义 异常:阻止当前方法或作用域继续执行的问题.虽然java中有异常处理机制,但是要明确一点,决不应该用"正常"的态度来看待异常.绝对一点说异常就是某种意义上的错误,就是问题,它可能会导致程序失败.之所以java要提出异常处理机制,就是要告诉开发人员,你的程序出现了不正常的情况,请注意. 记得当初学习java的时候,异常总是搞不太清楚,不知道这个异常是什么意思,为什么会有这个机制?但是随着知识的积累逐渐也

浅谈Java虚拟机

最近发现MDT推出去的系统的有不同问题,其问题就不说了,主要是策略权限被域继承了.比如我们手动安装的很多东东都是未配置壮态,推的就默认为安全壮态了,今天细找了一下,原来把这个关了就可以了. 浅谈Java虚拟机,布布扣,bubuko.com

浅谈Java中的对象和引用

浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是"对象和对象引用",很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起了解一下对象和对象引用之间的区别和联系. 1.何谓对象? 在Java中有一句比较流行的话,叫做"万物皆对象",这是Java语言设计之初的理念之一.要理解什么是对象,需要跟类一起结合起来理解.下面这段话引自<Java编程思想>中的一段原话: "按照通

浅谈Java中的equals和==

浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str2 = new String("hello"); 3 4 System.out.println(str1==str2); 5 System.out.println(str1.equals(str2)); 为什么第4行和第5行的输出结果不一样?==和equals方法之间的区别是什么?如果在初

浅谈Java throw, throws, try catch异常处理

1.throws关键字通常被应用在声明方法时,用来指定可能抛出的异常.多个异常可以使用逗号隔开.当在主函数中调用该方法时,如果发生异常,就会将异常抛给指定异常对象.如下面例子所示: public class Shoot {   创建类 static void pop() throws NegativeArraySizeException { //定义方法并抛出NegativeArraySizeException异常 int [] arr = new int[-3];//创建数组 } public

浅谈Java中的hashcode方法 - 海 子

浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 根据这个方法的声明可知,该方法返回一个int类型的数值,并且是本地方法,因此在Object类中并没有给出具体的实现. 为何Object类需要这样一个方法?它有什么作用呢?今天我们就来具体探讨一下hashCode方法. 一.hashCode方法的作用 对于包含容器类型的程

浅谈Java中的对象和对象引用

浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起了解一下对象和对象引用之间的区别和联系. 1.何谓对象? 在Java中有一句比较流行的话,叫做“万物皆对象”,这是Java语言设计之初的理念之一.要理解什么是对象,需要跟类一起结合起来理解.下面这段话引自<Java编程思想>中的一段原话: “按照通俗的说法,每个对象都是某个类(class)的一个实