一、什么是内部类?

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

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

  为什么我们要不走寻常路,把一个类定义在另一个类的内部呢?这样到底是出于什么目的呢?其实内部类是为了弥补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,那是因为同一个类中可能有两个以上同名的局部内部类。它们在不同的方法中定义。

aaarticlea/png;base64,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" alt="" />  

六、匿名内部类

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

  格式 :

      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来让该引用不可改变。

【JAVA】浅谈java内部类的更多相关文章

  1. 浅谈Java的throw与throws

    转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...

  2. 浅谈Java中的equals和==(转)

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...

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

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  4. 浅谈Java中的equals和==

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: String str1 = new String("hello"); String str2 = ...

  5. 浅谈JAVA集合框架

    浅谈JAVA集合框架 Java提供了数种持有对象的方式,包括语言内置的Array,还有就是utilities中提供的容器类(container classes),又称群集类(collection cl ...

  6. 浅谈java性能分析

    浅谈java性能分析,效能分析 在老师强烈的要求下做了效能分析,对上次写过的词频统计的程序进行分析以及改进. 对于效能分析:我个人很浅显的认为就是程序的运行效率,代码的执行效率等等. java做性能测 ...

  7. 浅谈Java中的深拷贝和浅拷贝(转载)

    浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...

  8. !! 浅谈Java学习方法和后期面试技巧

    浅谈Java学习方法和后期面试技巧 昨天查看3303回复33 部落用户大酋长 下面简单列举一下大家学习java的一个系统知识点的一些介绍 一.java基础部分:java基础的时候,有些知识点是非常重要 ...

  9. 浅谈Java中的深拷贝和浅拷贝

    转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...

  10. 【转】浅谈Java中的hashcode方法(这个demo可以多看看)

    浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native i ...

随机推荐

  1. 解决各大浏览器兼容问题hack

    解决各大浏览器兼容问题hack,IE6/ IE7/ IE8/ IE9/ Firefox/ Opera/ Webkit/ Chrome/ Safari. 浏览器兼容是网站前端页面制作最基本的问题,通常I ...

  2. Delphi 调用netsh命令修改IP地址

    Delphi 调用netsh命令修改IP地址 先介绍一下Netsh命令的使用方法: 在这里跟大家介绍几个简单的指令 1.Show IP 1.1Cmd Mode 直接在cmd下面输入 netsh int ...

  3. HDU 2222 Keywords Search(AC自动机模板题)

    学习AC自动机请戳这里:大神blog........ 自动机的模板: #include <iostream> #include <algorithm> #include < ...

  4. 编写一个Java应用程序,设计一个汽车类Vehicle,包含的属性有车轮个数 wheels和车重weight。小车类Car是Vehicle的子类,其中包含的属性有载人数 loader。卡车类Truck是Car类的子类,其中包含的属性有载重量payload。每个 类都有构造方法和输出相关数据的方法。最后,写一个测试类来测试这些类的功 能。

    package car; public class Vehicle { //定义成员变量 private int wheels; private double weight; public int g ...

  5. mysql 索引建立

    如何建立mysql索引? 创建索引原则 1.左前缀原则 : mysql索引匹配会从右匹配,到遇到( >  < between like)终止.如 我们建立索引(a,b,c,d), a = ...

  6. java Swing图形化界面

    学过java的人应该对java的图形化界面很是反感,特别是接触java不久的人.如果想和其他语言那样用鼠标拖拽,可以使用wondosbulider插件.但是用起来也不是那么方便.当然对于不乐意写代码的 ...

  7. Android设计模式系列-适配器模式

    对于android开发者来说起,适配器模式简直太熟悉不过,有很多应用可以说是天天在直接或者间接的用到适配器模式,比如ListView.ListView用于显示列表数据,但是作为列表数据集合有很多形式, ...

  8. C++ “读取位置 0x****** 时发生访问冲突”的可能原因

    转自:http://shansun123.iteye.com/blog/680066 这种错误的意思一般是指访问了不属于自己的内存空间,出现这种错误有几种原因: 1.给一个数组分配了比较小的内存空间, ...

  9. android常见错误--INSTALL_FAILED_DEXOPT

    出现上面的问题,是由于手机的内存不足导致的,需要清理一下手机的内存,然后就可以了

  10. zookeeper使用场景【转】

    分布式网站架构后续:zookeeper技术浅析   Zookeeper是hadoop的一个子项目,虽然源自hadoop,但是我发现zookeeper脱离hadoop的范畴开发分布式框架的运用越来越多. ...