一:内部类概述

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

二:内部类的创建

  我们都知道类的创建语法(简略)如下  

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

而内部类的创建就是把该类放在外部类的 同属性的位置或方法(包括构造方法)内    定义例下(希望大家可以看懂)

public class OutClass{
  public OutClass(){ //构造方法内创建内部类
    class C{}
  }
(修饰符)class A{} #局部内部类(同属性的位置)
public B getB(){ #简称方法内部类(方法的内部)
class B{}
return new B();
}
}  
####在次都忽略了修饰符,如果加上了修饰符如(static | public |private),会影响内部类的可见范围或和外围类的关系(如static),详细信息可参考修饰
符(和修饰符的用法及其相识)的讲解,和下文,因为篇幅有限不可能全面讲到。

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

内部类的创建方式有两种
方法一:在外围类环境下(),直接通过new 关键字和普通类一样创建
方法二:通过外围类实例创建,具体细节如下
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命令运行
备注:如果你想创建某些公共代码,只想让默些特定类(实现了该接口的类)拥有。就可用该接口内部了特性。

测试: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中内部类这一节讲到了闭包的概念,他是这样定义闭包的:闭包是一个可调用的对象,它记录了一些信息(即外部类对象的一些信息,这些信息并没有显现的展示给内部了对象,而是以一种特殊的形式OutClass_name.this的形式展示给了自己),这些信息来自创建它的作用域。通过这个定义,可以看出内部类是面向对象的闭包(即内部类就是java中一种闭包),它不仅包含外围类对象的信息,还自动拥有一个指向外部类的引用,在此作用域内,内部类可以有权操作所有成员,包括private成员。

ThinkInJava之内部类的更多相关文章

  1. JAVA基础之内部类

    JAVA基础之内部类 2017-01-13 1.java中的内部类都有什么?! 成员内部类 局部内部类 匿名内部类 静态内部类 2.内部类详解 •成员内部类 在一个类的内部再创建一个类,成为内部类 1 ...

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

    提起java内裤类(innerClass)很多人不太熟悉,实际上类似的概念在c++里面也有,那就是嵌套类(Nested Class),关于这俩者的区别,在下文中会有对比.内部类从表面上看,就是在类中定 ...

  3. Java类成员之内部类

    内部类含义: 在Java中允许一个类的定义位于另一个类的内部,前者称为内部类,后者称为外部类. Inner class 一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称. Inner ...

  4. java之内部类详解

    序言 有位小同学要我写一篇这个的总结,我说那好吧,那就动手写总结一下这个内部类的知识,感觉这个在面试中也会经常遇到,内部类.反射.集合.IO流.异常.多线程.泛型这些重要的基础知识大家都比较容易记不住 ...

  5. Java核心技术点之内部类

    1. 为什么要使用内部类     内部类就是定义在一个类内部的类,那么为什么要使用内部类呢?主要原因有以下几点:第一,内部类中定义的方法能访问到它所在外部类的私有属性及方法:第二,外部类无法实现对同一 ...

  6. 黑马程序员——JAVA基础之内部类,匿名内部类

    ------- android培训.java培训.期待与您交流! ---------- 内部类 将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类). 内部类访问特点: •  内部 ...

  7. java之内部类与匿名内部类

    Java 内部类 分四种:成员内部类.局部内部类.静态内部类和匿名内部类. 1.成员内部类: 即作为外部类的一个成员存在,与外部类的属性.方法并列. 注意:成员内部类中不能定义静态变量,但可以访问外部 ...

  8. 学习Android之内部类

    java语言允许在类中再定义类,这种在其它类内部定义的类就叫内部类.内部类又分为:常规内部类.局部内部类.匿名内部类和静态嵌套类四种.我们内部类的知识在Android手机开发中经常用到. 一.常规内部 ...

  9. C++之内部类(嵌套类)与外部类及友元

    本人能力.精力有限,所言所感都基于自身的实践和有限的阅读.查阅,如有错误,欢迎拍砖,敬请赐教——博客园:钱智慧. 先上代码: class Outer { public: Outer(){m_outer ...

随机推荐

  1. SpringMVC是怎么工作的,SpringMVC的工作原理

    SpringWeb MVC 是怎么工作的,SpringMVC的原理,SpringMVC源码 分析. 介绍 SpringWeb MVC是Spring Framework中的一部分,当我们需要使用spri ...

  2. javascript中的浅拷贝ShallowCopy与深拷贝DeepCopy

    拷贝,在js中,分为浅拷贝和深拷贝.这两者是如何区分的呢?又是如何实现的呢? 深浅拷贝的区分 首先说下,在js中,分为基础数据类型和复杂数据类型, 基础数据类型:Undefined.Null.Bool ...

  3. 公众号用户发送消息后台PHP回复没有反应的解决办法

    1.问题:微信公众平台官方提供下载的示例代码中,使用$postStr =$GLOBALS["HTTP_RAW_POST_DATA"];来获取微信服务器推送的消息数据.但是有的开发者 ...

  4. vue v-if 和 v-show 的知识点

    1.v-if 的特点: 实现方式:根据后面数据的真假判断是否重新删除或创建元素. 性能消耗:有较高的切换性能消耗. 编译过程:v-if 切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的 ...

  5. Linux-网络综合实验

    题目要求:财务部门有俩台机器acc-1和acc-2,it部门有俩台机器it-2和it-2,要求acc机器互通,it机器互通,财务部和it部机器通过路由器互通

  6. 网络克隆 主要是 PXE网卡启动 随笔

  7. Run Keyword And Ignore Error,Run Keyword And Return Status,Run Keyword And Continue On Failure,Run Keyword And Expect Error,Wait Until Keyword Succeeds用法

    *** Test Cases ***case1 #即使错误也继续执行,也不记录失败,且可以返回执行状态和错误信息 ${Run Keyword And Ignore Error status} ${st ...

  8. [转]玩转图片Base64编码

    转自:[前端攻略]:玩转图片Base64编码 图片处理在前端工作中可谓占据了很重要的一壁江山.而图片的 base64 编码可能相对一些人而言比较陌生,本文不是从纯技术的角度去讨论图片的 base64 ...

  9. HTTP 报文格式

    (a)GET,POST,PUT(更新)DELETE(删除) 首行中,请求报文只需包含路由,因为在发送请求前,tcp连接已经创建,协议版本 Header: 接收类型 (b)版本 + 状态码 Header ...

  10. pytroch nn.Module源码解析(1)

    今天在写一个分类网络时,要使用nn.Sequential中的一个模块,因为nn.Sequential中模块都没有名字,我一时竟无从下笔.于是决定写这篇博客梳理pytorch的nn.Module类,看完 ...