http://www.cnblogs.com/wenruo/p/5387995.html

内部类 就是在类中嵌套的另一个类。

非静态内部类

创建内部类的方式就是把类定义在外部类里面。

class Out { class In { } }

内部类对于外部类是特殊的,内部类可以访问到外部类的所有成员,包括私有成员。

class Outer {
private String str = "Outer";
class Inner {
public Inner() {str = "Inner";}
}
}

当生成一个内部类对象的时候,它自动和它的外部类有联系,所以要创建内部类对象,必须先有外部类对象。

内部类的类型在外部类除外部类静态方法外不能直接使用内部类的名字,应为OuterClassName.InnerClassName。

内部类可以为私有权限,当内部类为私有时,外部类外对内部类是不可见的。内部类不能有static的域,除非是final的。

创建内部类的方法:

1,外部类方法发返回内部类的引用。

2,通过.new语法实现。

class Outer {
class Inner { } public Inner getInner() {
return new Inner();
}
} public class Test {
public static void main(String args) {
Outer out = new Outer();
Outer.Inner in = out.new Inner();
Outer.Inner in1 = out.getInner();
}
}

在内部类通过OuterClassName.this可以访问外部类对象。

class Outer {
int a = 17;
class Inner {
int a = 3;
public void f() {
System.out.println(this.a + " " + Outer.this.a);
}
}
} public class Test {
public static void main(String[] args) {
Outer out = new Outer();
Outer.Inner in = out.new Inner();
in.f();
}
} // output:3 17

类也可以定义在代码块,包括方法内部。这样类的作用域也就限制在方法内部。此时内部类不能访问外部类,因为它不是外部类的一部分,但是它可以访问当前代码块的常量。

【名字实在是很糟糕

interface Inf {
void f();
} class Outer {
public Inf f() {
class Inner implements Inf {
public void f() {
System.out.println("Inner");
}
}
return new Inner();
}
} public class Test{
public static void main(String[] args) {
Outer out = new Outer();
Inf inf = out.f();
inf.f();
}
}

在这个例子中,通过向上转型为接口类型,完全隐藏了具体实现。

匿名内部类

匿名内部类就是没有名字的内部类aaarticlea/png;base64,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" alt="" />使用样例

interface Contents {
int value();
} public class AnonymousInnerClassTest {
public Contents contents() {
return new Contents() {
private int i = 11;
public int value() { return i; }
};
}
public static void main(String[] args) {
AnonymousInnerClassTest a = new AnonymousInnerClassTest();
Contents c = a.contents();
System.out.println(c.value());
}
}

乍一看很奇怪,但其实很方便的使用方法。在需要使用类的地方直接写一个类的定义。

匿名内部类和在方法中定义类使用功能差不多,区别就是匿名内部类只能产生一个对象。

很容易想到因为匿名类没有名字,而构造器的名字需要和类名一样,所以……它没!有!构!造!器!

如果基类需要有参数的构造器怎么办?只需要在new的时候加上参数就可以了。

public class A {
int i, j;
A(int i, int j) { this.i = i; this.j = j; }
} class B {
public A f(int i, int j) {
return new A(i, j) {
//...
};
}
}

那么如果一个匿名内部类需要构造器来初始化的时候怎么办呢?

在学习类的初始化顺序的时候知道,在构建类对象时是先执行非静态代码段再执行构造器。所以这里可以用代码块带到类似构造器的效果。

class B {
public void print() {}
} public class A {
public B getB() {
return new B() {
{ System.out.println("Inside Instance initialize."); }
public void print() { System.out.println("in anonymous f()"); }
};
} public static void main(String[] args) {
B b = new A().getB();
b.print();
}
}

如果定义一个匿名内部类,并且希望它使用一个在其外部定义的外部对象,那么编译器会要求其参数引用是final的。

Java8中,可以不是final了,但是默认是final的,在内部类不能改变。原因是在内部类,外部变量相当于形参,也就是在内部类改变对外部类无影响,就会造成数据不同步的问题。

interface I {}

public class A {
public static void main(String[] args) {
int x = 0;
new I() {
// x = 3; error
void f() { System.out.println(x); }
};
}
}

Java8中匿名内部类可以用lambda表达式代替,感觉超简洁。语法糖,写代码方便,不过也增加了阅读代码的难度。

interface A1 { void print(); }

class A2 {
public A1 f() {
return () -> { System.out.println("lambda expression."); };
}
} public class Test {
public static void main(String[] args) {
A1 a1 = new A2().f();
a1.print();
}
}

略过略过,以后再学,,,

迭代器实现

interface Iterator {
int next();
boolean hasNext();
} class Sequence {
private int[] items;
private int next = 0;
public int size() {
return items.length;
}
public Sequence(int size) {
items = new int[size];
}
public void add(int x) {
items[next++] = x;
}
public Iterator iterator() {
return new Iterator() {
int i = 0;
public int next() {
return items[i++];
}
public boolean hasNext(){
if (i == next) return false;
return true;
}
};
}
} public class Test {
public static void main(String[] args) {
Sequence s = new Sequence(10);
s.add(1); s.add(3); s.add(5);
Iterator it = s.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}

静态内部类

静态内部类常被称作嵌套类。静态内部类和外部类联系不是很大。

创建静态内部类的对象,并不需要外部类的对象。

不能从嵌套类的对象中访问非静态的外围类对象。

普通的内部类不能有static数据和static字段,也不能包含嵌套类,但是嵌套类可以包含所有这些东西。

class B {
static class C {
}
} public class A {
public static void main(String[] args) {
B.C c = new B.C();
}
}

内部类的继承

既然内部类对象一定要有某个关联外部类对象,那么继承自内部类的子类也一定需要外部类对象。

class WithInner {
public WithInner() {
System.out.println("外部类");
}
class Inner {
public Inner() {
System.out.println("内部类");
}
}
} public class InheritInner extends WithInner.Inner {
InheritInner(WithInner wi) {
wi.super();// 必须使用这样的语法 外部类对象引用+.super
System.out.println("继承自内部类的类");
}
public static void main(String[] args) {
WithInner wi = new WithInner();
InheritInner ii = new InheritInner(wi);
}
} /*
外部类
内部类
继承自内部类的类*/

内部类不能被重写,如下,此时A.Inner 和 B.Inner是毫不相关的两个类。

class A { class Inner {} }
class B extends A { class Inner {} }

继承类的内部类可以继承自基类的内部类 此时不再需要上面继承内部类的构造器

class A {
class B { }
} class A1 extends A {
class B extends A.B { }
}

内部类的名字

每个类都会生成一个.class文件。内部类的名字是:外部类名$内部类名.class,匿名内部类也有名字,外部类名$+一个数字来简单标识。

java 内部类的使用的更多相关文章

  1. Java内部类final语义实现

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

  2. Java内部类详解

    Java内部类详解 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法.今天我们就 ...

  3. 黑马----JAVA内部类

    黑马程序员:Java培训.Android培训.iOS培训..Net培训 黑马程序员--JAVA内部类 一.内部类分为显式内部类和匿名内部类. 二.显式内部类 1.即显式声明的内部类,它有类名. 2.显 ...

  4. java 内部类 *** 最爱那水货

    注: 转载于http://blog.csdn.net/jiangxinyu/article/details/8177326 Java语言允许在类中再定义类,这种在其它类内部定义的类就叫内部类.内部类又 ...

  5. java内部类和匿名内部类

    内部类即是包含在类里面的又一个类. java内部类分为: 成员内部类.静态嵌套类.方法内部类.匿名内部类 . 内部类的共性 (1).内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.clas ...

  6. Java内部类小程序(成员内部类,静态内部类,匿名内部类)

    /** * 测试java内部类(成员内部类,静态内部类,匿名内部类) * 局部内部类不常用,就不写了. * @package :java05 * @author shaobn * @Describe ...

  7. [转] Java内部类详解

    作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置 ...

  8. java内部类的作用分析

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

  9. 9)Java内部类(Inner Class)

      内部类:不可以有静态数据,静态方法或者又一个静态内部类      内部类的优点:隐藏类的细节,内部类可以声明为私有.内部类可以访问外部类的对象(包括private) 静态内部类:可以有静态数据,静 ...

  10. JAVA内部类(转)

    源出处:JAVA内部类 在java语言中,有一种类叫做内部类(inner class),也称为嵌入类(nested class),它是定义在其他类的内部.内部类作为其外部类的一个成员,与其他成员一样, ...

随机推荐

  1. python中unicode、utf8、gbk等编码问题

    转自:http://luchanghong.com/python/2012/07/06/python-encoding-with-unicode-and-gbk-and-utf8.html 概要:编码 ...

  2. Maven打包时囊括本地依赖的jar包

    在开发中,偶尔会遇到一个问题:某些比较冷门的包,maven服务器上没有,而我们又必须用,通常情况下会在项目中建立一个lib文件夹.将这些包copy进去并加入buildpath,开发就可以继续了,如下图 ...

  3. 微软在 .NET 3.5 新增了一个 HashSet 类,在 .NET 4 新增了一个 SortedSet 类,本文介绍他们的特性,并比较他们的异同。

    微软在 .NET 3.5 新增了一个 HashSet 类,在 .NET 4 新增了一个 SortedSet 类,本文介绍他们的特性,并比较他们的异同. .NET Collection 函数库的 Has ...

  4. arcgis 10.2 安装教程

    arcgis 10.2 安装教程(含下载地址)_百度经验 http://jingyan.baidu.com/article/fc07f98911b66912ffe5199b.html arcgis 1 ...

  5. *IntelliJ IDEA使用Hibernate连接数据库

    在IntelliJ IDEA中配置MySQL Database.

  6. etc/ld.so.conf的使用说明

    这个文件记录了编译时使用的动态链接库的路径.默认情况下,编译器只会使用/lib和/usr/lib这两个目录下的库文件如果你安装了某些库,比如在安装gtk+-2.4.13时它会需要glib-2.0 &g ...

  7. Java基于Servlet 验证吗

    req.setCharacterEncoding("utf-8");        resp.setContentType("text/html;charset=utf- ...

  8. 【剑指offer】判断二叉树是否为平衡二叉树

    2013-09-03 14:16:51 面试题39:求二叉树的深度.判断二叉树是否为平衡二叉树 小结: 根据平衡二叉树的定义,需要判断每个结点,因此,需要遍历二叉树的所有结点,并判断以当前结点为根的树 ...

  9. WIFI(1)WIFI直连 + socket 可以用来实现类似蓝牙传输数据的功能

    WIFI 直连简介 从Android4.0(API Level=14)开始,允许通过Wi-Fi模块在两个移动设备之间建立直接连接(这种技术称为Wi-Fi Direct),这种连接不需要无线路由作为中介 ...

  10. ListView中使用type需要注意的东西 java.lang.ArrayIndexOutOfBoundsException: length=2; index=2 addScrapView

    ListView中使用type需要注意的东西 在使用ListView时,如果使用了getItemViewType, 记得他的值一定要是从0开始计数的. 且要覆盖getViewTypeCount方法.并 ...