ThinkInJava之内部类

一:内部类概述

  将一个类的定义放在另一个类的内部,这就是内部类。内部类是Java一种非常有用的特征,因为他允许你把一些逻辑相关的数据组织在一起,并控制它的可见性。
二:内部类的创建

  我们都知道类的创建语法如下  

[public |...] class 类名 [implements|....]{
    定义属性(注意不同的修饰符(如public ....))
    定义方法语法(构造方法或普通方法)
}    

而内部类的创建就是把该类放在同属性或方法内定义例如

public class OutClass{
    (修饰符)class A{} #局部内部类
    public B getB(){  #简称方法内部类
         class B{}         return new B();
    }
}  

三:外部类访问(创建)内部类(和内部类的修饰符有关系(如private public  static 。。。。))

public class Parcel2 {
    class Contents{
        private int i = 11;
        public int values() {
            return i;
        }
    }
    public Contents contents() {
        return new  Contents(); #在外部类环境内创建
    }
    public static void main(String[] args) {
        Parcel2 parcel2 = new Parcel2();
                #注意这是两种创建内部类的方法
        Contents contents = parcel2.contents(); #在外部类环境内直接创建
        Contents contents = parcel2.new Contents();#通过外部类对象和关键字new创建内部类
    }
}    

备注:其它很多博客对内部类做了分类,这些分类也不外乎就是定义内部时用的修饰符和内部类定义位置的不同给内部起的名字而已。例如

  成员内部类:同属性一样定义(修饰符一般是public或private)。

  匿名内部类:即一个方法接受一个接口(interfaceA)类型的类。在其它类中调用这个方法,直接通过new interfaceA()这个接口并实现了该接口的所有方法,new interfaceA就是匿名内部了。

  方法内部类:就是定义在外类普通方法内的内部类。

局部内部类:就是定义在构造方法内的内部类。

  嵌套内部类:就是把定义内部了时用static关键字修饰的内部类。这个类我想多说点,普通内部类对象隐式的保存了一个外部类对象的引用,然而内部类通过static修饰就不一样了,该内部类就和外部类完全分离了,即不需要通过外部类对象创建内部类,内部了没有关联的外部类引用了。

  接口内部类:外部类不是一个类,而是一个接口,接口内定义了一个内部类,该内部类可以实现自己,案例如五 接口内部了

四:关键字this 和new

4.1  new 的用法已经介绍过(通过外部类实例创建内部类实例)

4.2 this 通过OutClass.this 方式可访问创建自自己的的外部类实例(非常重要注意理解,有助于帮助我们理解为什么外部类对象的属性(包括private)完全报漏给内部类,检验如下

public class OutClass {
    void print() {
        System.out.println("id:"+ this.hashCode()+"我是外部类的方法");
    }
    class InnerClass{
        void print() {
            System.out.println("我是内部类的方法");
            System.out.println("___________");
            OutClass.this.print();//内部类内访问创建它的外部类实例,并调用外部类的方法
        }
    }
    public static void main(String[] args) {
        OutClass outClass = new OutClass();
        System.out.println("id:" + outClass.hashCode());
        InnerClass innerClass = outClass.new InnerClass();
        innerClass.print();
    }
}
结果:
id:865113938
我是内部类的方法
___________
id:865113938我是外部类的方法分析结果,我们发现打印的hashCode()值相同,可知两次打印都是同一个对象的引用地址。

五:接口内部类

  正常情况下,不能在接口内放置任何代码,但嵌套类可以作为接口的一部分,你放入接口中的任何类都自动转化为public和static,因为类是static,只是将

嵌套类置于接口的命名空间内,这并不违反接口规则。你可以在内部类中实现外围接口如下

public interface ClassInInterface {    void howdy();
    class Test implements ClassInInterface{
        @Override
        public void howdy() {
            System.out.println("我是接口内部类接口");
        };
        public static void main(String[] args) {
            new Test().howdy();
        }
    }
}注意:在编译器内(eclipse),无法直接运行该main方法,可通过Javac编译代码,然后用Java命令运行备注:如果你想创建某些公共代码,只想让默些特定类(实现了该接口的类)拥有。就可用该接口内部了特性。

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Menlo }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Menlo; color: #777777 }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Menlo; color: #7e504f }
span.s1 { color: #931a68 }
span.s2 { color: #000000 }
span.s3 { color: #0326cc }
span.s4 { color: #3933ff }
span.s5 { color: #7e504f }
span.Apple-tab-span { white-space: pre }

测试:ClassInInterface

public class ClassInInterfaceImpl implements ClassInInterface{

@Override

public void howdy() {

new Test().howdy();

System.out.println("我自己的方法");

}

public static void main(String[] args) {

ClassInInterfaceImpl classInInterfaceImpl = new ClassInInterfaceImpl();

classInInterfaceImpl.howdy();

}

}

结果:

我是接口内部类接口

我自己的方法

六:关于使用内部类的一些小结

  6.1:解决了java多重继承的问题。比如有个类需要继承其它两个类,然而Java只支持单继承,故我们可以通过编写一个内部类来继承另一个类的我们需要的类(当然我们也可以通过组合的方式来完成相识功能)

  6.2:封装一些功能,只让特定的类拥有该方法。例如接口内部类,只有实现了该接口的类才拥有使用特定功能。

  6.3:一个类中要实现一个接口方法的不同功能。

 何时(什么情况下)使用内部类?请注意这个问题(引用ThinkInJava),如果只是需要一个接口的引用,为什么不通过外围类实现那个接口呢?答案是:如果这能满足需求,那么就行该这样做(即不用内部类)

同时,因为内部类引用了外部类的对象的地址,导致外部类始终有一个对象在引用他,如果不刻意手动清空内部类,就会导致内存泄漏。如下

public class Clear {
    @Override
    protected void finalize() throws Throwable {
        // TODO Auto-generated method stub
        super.finalize();
        System.out.println("垃圾回收器要清理我");
    }
    public static void main(String[] args) {
        Clear clear = new Clear();
        代码1.//InnerClass innerClass = clear.new InnerClass();
        代码2.//innerClass = null     代码3.//new Clear().new InnerClass()        clear = null;//        System.gc();
    }
    class InnerClass{
    }
}

结果:垃圾回收器要清理我

如果我们把代码1注射打开,就不会执行finalize()方法,必须同时把代码2也要打开。如果是代码3的写法?那么垃圾怎么回收外部类呢??(就导致了内存泄漏)

备注:在thinkInJava中内部类这一节讲到了闭包的概念,他是这样定义闭包的:闭包是一个可调用的对象,它记录了一些信息,这些信息来自创建它的作用域。通过这个定义,可以看出内部类是面向对象的闭包,它不仅包含外围类对象的信息,还自动拥有一个指向外部类的引用,在此作用域内,内部类可以有权操作所有成员,包括private成员。

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Menlo }

原文地址:https://www.cnblogs.com/jinliang374003909/p/10351877.html

时间: 2024-10-17 09:12:40

ThinkInJava之内部类的相关文章

java基础之内部类

java内部类,本是非常基础的,在分析一些开源框架源码时候或者看jdk源码的时候,就会发现用到大量的内部类.但是在实际工作中,尤其对于新手来说,根本不知道内部类有什么用处.说白了还是对内部类的基本原理不够清晰,没有掌握好这个基础,所以才不知道内部类有什么用处. 本人也是一边总结基础一边学习一边成长中. 关于内部类: java有四种内部类: ①静态内部类(static inner class) ②成员内部类(member inner class) ③局部内部类(local inner class)

java之内部类

1 public class RedCowForm { 2 static String formName ; 3 RedCow cow ; //内部类声明对象 4 RedCowForm(){} 5 RedCowForm(String s) 6 { 7 cow =new RedCow(150,112,5000); 8 formName= s; 9 } 10 public void showCowMess() 11 { 12 cow.speak(); 13 } 14 class RedCow //内

Android进程间通信之内部类作为事件监听器

在Android中,使用内部类可以在当前类里面发用改监听器类,因为监听器类是外部类的内部类,所以可以自由访问外部类的所有界面组件.以下是一个调用系统内部类实现短信发送的一个例子: SMS类: package com.example.msmlistener; import android.app.Activity; import android.app.PendingIntent; import android.content.Intent; import android.telephony.Sm

JavaSE入门学习14:Java面向对象之内部类

一内部类概述 内部类(Inner Class)就是定义在另外一个类里面的类.与之对应,包含内部类的类被称为外部类. 内部类的主要作用如下: A内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类. B内部类的方法可以直接访问外部类的所有数据,包括私有的数据. C内部类所实现的功能使用外部类同样可以实现,只是有时使用内部类更方便. 内部类可分为以下几种: A成员内部类 B静态内部类 C方法内部类 D匿名内部类 二成员内部类 内部类中最常见的就是成员内部类,也称为普

java之内部类(InnerClass)----非静态内部类、静态内部类、局部内部类、匿名内部类

提起java内裤类(innerClass)很多人不太熟悉,实际上类似的概念在c++里面也有,那就是嵌套类(Nested Class),关于这俩者的区别,在下文中会有对比.内部类从表面上看,就是在类中定义了一个类(下文可以看到,内部类可以在很多地方定义),而实际上并没有那么简单,乍看上去内部类似乎有些多余,他的用处可能对于初学者来说并不是那么显著,但是随着对他的深入了解,你会发现java的设计者在内裤类上面的确是用心良苦.学会使用内部类,是掌握java高级编程的一部分,他可以让你更优雅的设计你的程

Effective Java之内部类

Effective Java中对类的权限,接口等的要求,总结起来就是够用就行,不要赋予过多的访问权限,类的定义也是,如果某个类只会在类的内部使用,那就将该类定义为内部类吧. 内部类分为四种: 1.静态内部类:静态内部类就是在class前面多了static关键词的内部类,这种类和类的静态方法和静态变量一样,针对类本省进行操作,在静态内部类中可以随意访问其所在类的静态方法和静态变量. 2.非静态内部类:和静态内部类相对于,其实在类内部定义的所有东西只是受到访问修饰符的限制,所以非静态内部类和类的非静

每天学一点Scala之内部类

1.  scala 里同样可以定义内部类 2.  每个外部类的对象的内部类,都是不同的类,因此,存数组时,要注意 3.  内部类可以访问外部类的私有属性,反之不行 package com.xej.learning.class_learning /**   * Created by erjun on 2017/8/28.   * 内部类测试   */ private[class_learning] class Kafka{    //定义一个内部类    class InnerKafka(val 

JavaSE之内部类

内部类分类: 成员内部类:在成员位置声明的类,叫成员内部类. 局部内部类:在局部变量定义的类,叫局部内部类. 1.成员内部类: 非静态成员内部类://格式 外部类名.内部类名 对象名=new 外部类().new内部类(); package cn.itcast.inner; public class InnerDemo2 { public static void main(String[] args) { //格式 外部类名.内部类名.内部类名.对象名=外部类对象.内部类对象 OuterClass

java 基础之内部类

内部类的使用 1内部类对象的创建: 非静态内部类:Outer.Inner oi  = new Outer().new Inner(); 静态内部类:Outer.Inner oi  = new Outer().Inner(); 2内部类的方法调用 非静态内部类和静态内部类的非静态方法:oi.test(); 静态内部类的静态方法:Inner.test(); public class Test { public static void main(String[] args) { new Test().