一、简介

因为现在是Android开发实习生。发现在发展过程中越来越多,但他们知道什么时候该使用真实的情况,但没有获得,例如,使用内部类,因此,学习和自己的总结后发现,通过互联网的信息,家分享,如有不当之处。万望指出。

二、内部类

内部类是指在一个外部类的内部再定义一个类,是一个编译时的概念。一旦编译成功,内部类与其外部类就会成为全然不同的两类,仅仅是内部类的前面会冠以外部类的类名和$符号,如一个outer类内部定义了一个inner的内部类,那么编译完毕后会生成outer.class和outer$inner.class两个类,因此内部类的成员变量与方法能够与外部类同样。
从内部类的定义上来看。事实上内部类严重破坏了良好的代码结构。那么为什么还要使用内部类呢?由于内部类能够任意使用外部类的成员变量(包含私有的)而不用生成外部类对象,这也是内部类的唯一长处。

三、内部类的分类及演示样例

        内部类分为成员内部类、局部内部类、静态内部类和匿名内部类。以下针对各个内部类进行介绍:

(1)成员内部类

作为外部类的一个成员存在,与外部类的属性、方法并列。成员内部类中能够訪问外部类的全部成员,当外部类的变量与内部类的变量名反复时,使用外部类名.this.变量名能够对外部类的变量进行调用。假设没有反复时可直接使用变量名进行调用。在普通外部类方法中訪问静态内部类可new出成员内部类对象进而直接调用当中的方法,而在静态外部类方法中须要先new出外部类对象,再调用外部类对象名.new 内部类的方式来获得成员内部类对象。

成员内部类中不能定义静态变量,由于成员内部类须要先创建了外部类,才干创建它自己的。

成员内部类能够使用外部类的私有成员和属性。同一时候其在外部类中定义了不可訪问的属性,这样就在外部类中实现了比外部类的private还要小的訪问权限。

演示样例代码例如以下:

/**
*
* @ClassName: MemberInnerClass
* @Description: 成员内部类
* @author ADAM
* @date 2014年7月25日 上午9:20:28
*
*/
public class MemberInnerClass {
private int i = 0; public class Inner {// 成员内部类可加权限修饰符
int i = 3; public void print() {
System.out.println(i);// 输出为内部类的i。值为3
System.out.println(this.i);// 输出为内部类的i,值为3
System.out.println(MemberInnerClass.this.i);// 输出外部类的i,值为0
}
} public void print() {
(new Inner()).print();// 外部类普通方法调用成员内部类直接new出内部类进行调用
} public static void main(String[] args) {
((new MemberInnerClass()).new Inner()).print();// 外部类静态方法中调用成员内部类首先new出外部类然后new出内部类进行调用
}
}

(2)局部内部类

即在方法中定义的内部类,与局部变量类似。在局部内部类前不加修饰符public或private。其范围为定义它的代码块。

局部内部类中不可定义静态变量。能够訪问外部类(即方法)中的变量。可是变量必须是final。局部内部类与外部类的命名重名时的调用方法与成员内部类同样,訪问局部内部类必须得先有外部类对象。

在类外不可直接生成局部内部类(保证局部内部类对外是不可见的)。要想使用局部内部类时须要生成外部类对象,对象再去调用方法,在方法中才干调用其局部内部内。

通过内部类与接口达到了一个强制的弱耦合,用局部内部类来实现接口。并在方法中返回接口类型,使局部内部类不可见。屏蔽实现类的可见性。

演示样例代码例如以下:

/**
*
* @ClassName: LocalInnerClass
* @Description: 局部内部类
* @author ADAM
* @date 2014年7月25日 上午10:36:26
*
*/
public class LocalInnerClass {
private int j = 3;
private int i = 2; public void test() {
MemberInnerClass memberInnerClass = new MemberInnerClass();
// 若要訪问其它类中的成员内部类仅仅能当该成员内部类的修饰符为public才可
// 否则编译错误,即成员内部类能够再类内部实现比private还要小的权限
memberInnerClass.new Inner();
final int i = 0;
class Inner {// 此处不得加上private等修饰符,否则编译错误
int i = 1; public void print() {
System.out.println(j);饰符。否则编译错误
System.out.println(i);// 此时输出局部内部类的i,外部方法中的变量仅仅能通过传參的形式进行调用
System.out.println(LocalInnerClass.this.i);// 此时输出的是外部类中的i
}
}
Inner inner = new Inner();// 局部内部类仅仅能在方法内实例化并进行调用
inner.print();
} public static void main(String[] args) {
(new LocalInnerClass()).test();
}
}

局部内部类不仅能够定义在方法中还能够定义在作用域内。下面提供两个Thinking in Java的样例

定义在方法内:

public class Parcel4 {
public Destination destination(String s) {
class PDestination implements Destination {
private String label; private PDestination(String whereTo) {
label = whereTo;
} public String readLabel() {
return label;
}
}
return new PDestination(s);
} public static void main(String[] args) {
Parcel4 p = new Parcel4();
Destination d = p.destination("Tasmania");
}
} <span style="line-height: 1.3em; font-family: 'Courier New', monospace; background-color: inherit;"> </span>

定义在作用域里:

public class Parcel5 {
private void internalTracking(boolean b) {
if (b) {
class TrackingSlip {
private String id;
TrackingSlip(String s) {
id = s;
}
String getSlip() {
return id;
}
}
TrackingSlip ts = new TrackingSlip("slip");
String s = ts.getSlip();
}
} public void track() {
internalTracking(true);
} public static void main(String[] args) {
Parcel5 p = new Parcel5();
p.track();
}
}

局部内部类也像别的类一样进行编译,仅仅是作用域有所不同。仅仅在该方法或者条件的作用域内才干使用。出了这些作用域则无法被使用。

(3)静态内部类

静态内部类也称为嵌套内部类,定义在类中,不论什么方法外。用static定义,静态内部类中能够定义静态或非静态的成员,其可用public、private等修饰符修饰,一般使用public修饰。方便调用,其仅仅能訪问外部类中的静态成员。外部类訪问静态内部类中的静态成员时直接使用内部类.静态成员,訪问静态内部类的非静态成员时先实例化静态内部类再通过对象訪问。

生成一个静态内部类不须要外部类对象成员。这是与成员内部类的差别,同一时候普通内部类不能有static方法和属性,也不能包括嵌套类,静态内部类的对象能够直接生成:外部类.内部类 对象名= new 外部类.内部类()就可以

注意:当类与接口(或者接口与接口)发生方法命名冲突时,必须使用内部类来实现。

用接口不能全然地实现多继承,用接口配合内部类才干实现真正的多继承。

演示样例代码例如以下:

/**
*
* @ClassName: StaticInnerClass
* @Description: 静态内部类
* @author ADAM
* @date 2014年7月25日 上午10:37:04
*
*/
public class StaticInnerClass {
private int i = 1;
public static int j = 1;
public int k = 0; public static class Inner {
private int i = 0;
private static int j = 0;// 可定义静态与非静态成员 public static void print() {
// System.out.println(k);// 编译错误,不得调用外部类中的非静态成员
System.out.println(new StaticInnerClass().i);//訪问外部类中的非静态成员变量须要先实例化外部类
System.out.println(j);
System.out.println(new StaticInnerClass().j);// 静态内部类使用外部类中的静态成员
}
} public static void main(String[] args) {
Inner.print();// 外部类静态方法或者非静态方法调用静态内部类中的静态成员时直接内部类名.成员就可以
StaticInnerClass.Inner inner = new StaticInnerClass.Inner();// 静态内部类的实例化不须要先实例化外部类
System.out.println(inner.i);// 訪问静态内部类中的非静态成员时须要先实例化静态内部类
}
}

通过内部类实现多继承演示样例代码例如以下:

/**
*
* @ClassName: Pencil
* @Description: 笔类
* @author ADAM
* @date 2014年7月25日 上午10:42:59
*
*/
public abstract class Pencil {
public abstract void write();
}
/**
*
* @ClassName: Eraser
* @Description: 橡皮擦类
* @author ADAM
* @date 2014年7月25日 上午10:43:28
*
*/
public abstract class Eraser {
public abstract void erase();
}
/**
*
* @ClassName: PencilWithEraser
* @Description: 多继承类
* @author ADAM
* @date 2014年7月25日 上午10:43:53
*
*/
public class PencilWithEraser {
private MyPencil pencil = new MyPencil();
private MyEraser eraser = new MyEraser(); private class MyPencil extends Pencil {//继承笔类 @Override
public void write() {
System.out.println("To Write");
} } private class MyEraser extends Eraser {//继承橡皮擦类
@Override
public void erase() {
System.out.println("To Erase");
} } // 本类自己的方法。调用继承类中的方法
public void write() {
pencil.write();
} public void erase() {
eraser.erase();
} public static void main(String[] args) {
PencilWithEraser pencilWithEraser = new PencilWithEraser();
pencilWithEraser.write();
pencilWithEraser.erase();
}
}

(4)匿名内部类

         用于继承其它类或是实现接口,并不须要添加额外的方法,仅仅是对继承方法的重写或实现,也使用于仅仅是为了得到一个对象实例,不须要知道事实上际类型,此时类名是没有意义的,也不须要被使用到。

演示样例代码例如以下:

/**
*
* @ClassName: AnonymousInnerClass
* @Description: 匿名内部类
* @author ADAM
* @date 2014年7月25日 上午10:38:25
*
*/
public class AnonymousInnerClass {
public void click(OnClickListener onClickListener) {
System.out.println("click,click");
} public static void main(String[] args) {
AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass();
anonymousInnerClass.click(new OnClickListener() {// 直接new出匿名内部类,不须要保存对象。一般用于继承其它类或是实现接口
@Override
public void onClick() {
System.out.println("Inner Click");
}
});
}
}

四、总结

因为眼下还是处于学习阶段,对于内部类的使用最多的也是成员内部类和匿名内部类。所以对于诸如非常仔细地去区分各个内部类的使用场景以及涉及到的更小的訪问权限的作用等方面体会并非非常深刻,之后有更进一步的学习会补上,也希望看到这篇博文的朋友假设有一些其它的见解或者补充或者是推荐学习的资料也能够提出来,这篇博文也是借鉴网上各位大神以及百科的相关资料,再自己手动编码验证总结果出,感恩节你大神,谢谢。






版权声明:本文博客原创文章。博客,未经同意,不得转载。

Java 内部类分析的更多相关文章

  1. java内部类的作用分析

    提起Java内部类(Inner Class)可能很多人不太熟悉,实际上类似的概念在C++里也有,那就是嵌套类(Nested Class),关于这两者的区别与联系,在下文中会有对比.内部类从表面上看,就 ...

  2. 【转】java内部类的作用分析

    转自:http://blog.csdn.net/ilibaba/article/details/3866537 另收另外一篇有空的时候看:http://jinguo.iteye.com/blog/71 ...

  3. Java集合分析

    Java集合分析 前言 从开始接触Java的时候, 就在强调的一个重要版块, 集合. 终于能够开始对它的源码进行分析, 理解, 如果不懂得背后的思想, 那么读懂代码, 也仅仅是读懂了 if else ...

  4. js闭包vs Java内部类

    前言: 昨天写了一个关于Java内部的博客,在内部类的最后一点中谈到了Java闭包的概念,他是这样定义闭包的:闭包是一个可调用的对象,它记录了一些信息,这些信息来自创建它的作用域.结合Java的内部类 ...

  5. 从字节码的角度看Java内部类与外部类的互相访问

    Java中non-static内部类为何可以访问外部类的变量?Java中外部类又为何可以访问内部类的private变量?这两个问题困扰过我一段时间,查了一些网上的答案,大多从“闭包”概念入手,理解起来 ...

  6. 夯实Java基础系列18:深入理解Java内部类及其实现原理

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  7. Java内部类final语义实现

    本文描述在java内部类中,经常会引用外部类的变量信息.但是这些变量信息是如何传递给内部类的,在表面上并没有相应的线索.本文从字节码层描述在内部类中是如何实现这些语义的. 本地临时变量 基本类型 fi ...

  8. Java 性能分析工具 , 第 3 部分: Java Mission Control

    引言 本文为 Java 性能分析工具系列文章第三篇,这里将介绍如何使用 Java 任务控制器 Java Mission Control 深入分析 Java 应用程序的性能,为程序开发人员在使用 Jav ...

  9. Java 性能分析工具 , 第 2 部分:Java 内置监控工具

    引言 本文为 Java 性能分析工具系列文章第二篇,第一篇:操作系统工具.在本文中将介绍如何使用 Java 内置监控工具更加深入的了解 Java 应用程序和 JVM 本身.在 JDK 中有许多内置的工 ...

随机推荐

  1. AJAX POST请求中參数以form data和request payload形式在servlet中的获取方式

    HTTP请求中,假设是get请求,那么表单參数以name=value&name1=value1的形式附到url的后面,假设是post请求,那么表单參数是在请求体中,也是以name=value& ...

  2. [POJ 3735] Training little cats (结构矩阵、矩阵高速功率)

    Training little cats Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9613   Accepted: 2 ...

  3. python学习1(小白记录)

    python创建cocos2d-x项目注意点1. 2.7.5版本号的.配置好环境变量之后.要切换到tools文件夹下.直接运行 python create_project.py ..........这 ...

  4. Thinkphp常用标签

    告:在使用下列所说的任何标签库都需要 HTML第一行加入 <tarlib name=”cx,html” /> 如果想单独引入cx标签库就直接写成<tarlib name=”cx” / ...

  5. Unity3D中的Update, FixedUpdate, LateUpdate的区别

    MonoBehaviour.Update 更新 当MonoBehaviour启用时,其Update在每一帧被调用. MonoBehaviour.FixedUpdate 固定更新 当MonoBehavi ...

  6. Git双机同步

    如果使用git init 初始化,当客户端仓库push内容时,服务器端仓库可以看到log,但是更新的文件不能显示,必须使用git reset --hard才能更新内容

  7. CodeForces 343D 线段树维护dfs序

    给定一棵树,初始时树为空 操作1,往某个结点注水,那么该结点的子树都注满了水 操作2,将某个结点的水放空,那么该结点的父亲的水也就放空了 操作3,询问某个点是否有水 我们将树进行dfs, 生成in[u ...

  8. Apache介绍

    怎样使用Apache许可证         若用户须要应用Apache许可证,请将下面演示样例使用适当的注视方法包括在作品源文件里,将括号"[]"中的字段以用户自身的区分信息来替换 ...

  9. 将ACCESS数据库迁移到SQLSERVER数据库

    原文:将ACCESS数据库迁移到SQLSERVER数据库 将ACCESS数据库迁移到SQLSERVER数据库 ACCESS2000文件 用ACCESS2007打开,并迁移到SQLSERVER2005里 ...

  10. oracle错误之 ora-01017

    ora-01017 现象描述: scott用户和其它建立的用户,都登的上.但sys和system用户登录不上 方案一(试过,不行): 1,打开目录:F:\app\Administrator\produ ...