1. 内部类的作用

内部类是一个独立的实体,可以用来实现闭包;能与外部类通信;内部类与接口使得多继承更完整

2. 内部类的分类

1)普通内部类

类的实例相关,可以看成是一个实例变量。内部类的类名由 “外部类.内部类” 确定。

普通内部类不能声明 static相关的变量或方法。内部类可以直接访问外部类的所有成员(包括 private成员),隐式或显式(外部类.this)。而外部类可以 new 内部类,实例相关的可以直接 new,static 相关(类相关)需要使用实例的引用去 引用.new。内部类 class 前可以添加 private 与 protected 表示只对其外部类或其子类有访问权限。

final class Demo {
private int m = 4; private Demo() {
System.out.println("Demo initial");
} private class Inner {
private int i = 23; Inner() {
System.out.println("Inner initial");
}
private void f() {
System.out.println("f method" + " i:" + this.i + " m:" + Demo.this.m);
}
} public static void main(String[] args) {
Demo demo = new Demo();
System.out.println("Dispatch Inner class");
Demo.Inner inn = demo.new Inner();
inn.f();
} }
/* out:
Demo initial
Dispatch Inner class
Inner initial
f method i:23 m:4 *///~

* 关于闭包

Java 中通过 内部类指向顶级类的指针(Demo.this) 访问顶级类中的(又称内部类所在词法作用域)变量。其中 Demo.this ,表示的是顶级类的上下文;而内部类中的 this (可省略)表示的是内部类上下文。

Js 中只有一个 this,它既可以访问函数体外部又可以访问函数体内部。先在内部寻找,如果找不到则去外部寻找。而去外部找就是所谓的闭包引用。闭包又称为词法闭包。

var myObject = {
foo: "bar",
func: function() {
var self = this;
console.log("outer func:" + this);
console.log("outer func: this.foo = " + this.foo);
console.log("outer func: self.foo = " + self.foo);
(function() {
console.log("inner func:" + this)
console.log("inner func: this.foo = " + this.foo);
console.log("inner func: self.foo = " + self.foo);
}());
}
}; myObject.func(); //output:
outer func:[object Object]
outer func: this.foo = bar
outer func: self.foo = bar
inner func:[object Window]
inner func: this.foo = undefined
inner func: self.foo = bar

* 注意:

在原型继承的情况下,如果函数无法找到其所有者/调用者(sush as  IIFE),那么在非严格模式下函数内的 this 指向 window 对象。关于变量,一般情况下 this 先访问该函数内部的变量,再去函数所在词法作用域寻找,如果还找不到则去 window 作用域寻找。而去 window 里找变量通常是危险的,这时就需要使用参数或其它方式保存变量。从 关于 lambda 表达式中的 this 一文中,可以得出:lambda 去上一个调用者/window 对象。 从 深入浅出 JavaScript 中的 this,而对于使用 new Foo() 构造函数调用,this 指向到新的对象,普通变量不受影响。
for (var i = 0; i < 5; i++) {
var btn = document.createElement('button');
btn.appendChild(document.createTextNode('Button ' + i));
btn.addEventListener('click', function(){ console.log(i); });
document.body.appendChild(btn);
} //提供两种基本解决思路: for (var i = 0; i < 5; i++) {
var btn = document.createElement('button');
btn.appendChild(document.createTextNode('Button ' + i));
btn.a = i
btn.addEventListener('click', function(){ console.log(this.a); });
document.body.appendChild(btn);
} for (var i = 0; i < 5; i++) {
var btn = document.createElement('button');
btn.appendChild(document.createTextNode('Button ' + i));
//使用 IIFE 的方式有个副作用,函数体内代码立即执行。而这里不应立即执行,故返回一个函数,延迟执行。
btn.addEventListener('click', (function(arg){ return function() {console.log(arg);} })(i));
document.body.appendChild(btn);
}

2)局部内部类

方法和作用域中的内部类称为局部内部类,只在其词法作用域中可被访问。可以重载构造器。

3)匿名内部类

匿名内部类引用外部类方法中的局部变量必须是 final的原因:对于外部类方法中的局部变量,在该方法调用完成后从栈中清除( remove from stack) ,这时匿名内部类对象将变得无法访问它们。如果将这些变量声明为 final,他们实际上将不再是一个变量而变成了常量,编译器将在编译时把它们替换为具体的常量。(也有观点认为局部变量整体复制,final 保证一致性。)

匿名内部类没有具名构造器,new Wrapper(x) {} 将值传递给基类的构造器。可以被匿名内部类直接引用,不需要 final。

abstract class Base {
public Base(int i) {
System.out.println("Base constructor, i=" + i + "\n");
} public abstract void f();
} class AnonymousConstructor {
private int m = 10000;
public Base getBase(int i, final int outer) {
return new Base(i) { //这里引用 局部变量 i,是被匿名内部类的基类使用,不需要声明 final。
{
System.out.println("AnonymousInnerClass instance initializer\n");
}
@Override
public void f() {
// 局部变量 outer 也是被匿名内部类直接使用,需要声明为 fianl
System.out.println("This variable must declare final first: " + outer + "\n"); // 不同于前面对局部变量 i 的使用,这里是匿名直接使用,则需要声明 final。否则报错!(java 8 或以上除外)
//System.out.println("This variable must declare final first: " + i + "\n"); // 对非局部变量 m 的使用,不需要声明 final。m 等同与 AnonymousConstructor.this.m
System.out.println(m); }
};
} public static void main(String[] args) {
AnonymousConstructor ac = new AnonymousConstructor();
Base base = ac.getBase(3, 9);
base.f();
}
}

4)嵌套类

如果不需要内部类对象与其外部类对象之间有联系,那么可以将内部类声明为 static,称之为静态内部类或嵌套类。特点是:创建嵌套类的实例不需要其外围类的实例;不能从嵌套类的实例中访问非静态的外围类的实例(没有 this 引用);嵌套类不会随外部类加载而初始化。接口内部的类自动是 public static 的,可以将嵌套类放入接口中,从而使得他们可以被该接口的不同实现所共用。

final class Demo {
private int m = 4;
private static int n = 6; private Demo() {
System.out.println("Demo initial");
} static class Inner {
private int i = 23; Inner() {
System.out.println("Inner initial");
}
private void f() {
System.out.println("f method" + " i:" + this.i + " n:" + Demo.n);
}
} public static void main(String[] args) {
// Demo.Inner inn = new Inner(); // Inner initial
// inn.f(); // f method i:23 n:6
new Demo(); // Demo initial
} }
/* out:
Demo initial *///~

*  关于 java 中的 interface:

正如 接口内部的类自动是 public static 的,类中 嵌套的接口 (nested interface)也是自动 "static" 的,并且能够被移除。同样的,interface  方法上的 "public" 和域名上的 "public final" 也可以被移除。嵌套 interface 示例:

public class Foo {
public interface Bar {
void callback();
}
public static void registerCallback(Bar bar) {...}
}
// ...elsewhere...
Foo.registerCallback(new Foo.Bar() {
public void callback() {...}
});

Java中的 内部类(吐血总结)的更多相关文章

  1. Java中的内部类(成员内部类、静态内部类、局部内部类、匿名内部类)

    Java中的内部类(成员内部类.静态内部类.局部内部类.匿名内部类) 神话丿小王子的博客主页 我们先看这样一段话:人是由大脑.肢体.器官等身体结果组成.而组成我们人体的心脏它也有自己的属性和行为(血液 ...

  2. Java 中的内部类

    前言 在第一次把Java 编程思想中的内部类这一章撸完后,有点印象.大概知道了什么时内部类,局部内部类,匿名内部类,嵌套内部类.随着时间的推移,自己慢慢的就忘记了,总感觉自己思考的东西不多,于是 看了 ...

  3. 【转】Java中的内部类和匿名类

       Java内部类(Inner Class),类似的概念在C++里也有,那就是嵌套类(Nested Class),乍看上去内部类似乎有些多余,它的用处对于初学者来说可能并不是那么显著,但是随着对它的 ...

  4. Java学习笔记二十:Java中的内部类

    Java中的内部类 一:什么是内部类: (1).什么是内部类呢? 内部类( Inner Class )就是定义在另外一个类里面的类.与之对应,包含内部类的类被称为外部类. (2).那为什么要将一个类定 ...

  5. Java中的内部类怎么用

    一.为什么需要内部类?java内部类有什么好处?为什么需要内部类? 首先举一个简单的例子,如果你想实现一个接口,但是这个接口中的一个方法和你构想的这个类中的一个方法的名称,参数相同,你应该怎么办?这时 ...

  6. Java中的内部类(回调)

    一.内部类的主要作用如下: 1. 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类 2. 内部类的方法可以直接访问外部类的所有数据,包括私有的数据 3. 内部类所 ...

  7. 【Java基础】4、java中的内部类

    内部类的分类:常规内部类.静态内部类.私有内部类.局部内部类.匿名内部类. 实例1:常规内部类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2 ...

  8. Java中的内部类————以及jdk1.8的lambda表达式

    一.内部类学习导图 1>.静态内部类: 使用static修饰符来修饰内部类,则这个内部类就属于外部类本身,而不属于外部类的某个对象.因此使用static修饰的内部类被称为静态内部类. publi ...

  9. Java基础(十五):Java 中的内部类

    问:什么是内部类呢? 答:内部类( Inner Class )就是定义在另外一个类里面的类.与之对应,包含内部类的类被称为外部类. 问:那为什么要将一个类定义在另一个类里面呢?清清爽爽的独立的一个类多 ...

随机推荐

  1. 00、Word Count

    1.开发环境 1.eclipse-jee-neon-3 2.scala-ide:http://download.scala-ide.org/sdk/lithium/e46/scala212/stabl ...

  2. Jetpack 架构组件 Paging 分页加载 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  3. ORACLE通过SQL将一行数据转换为多行

    转换前和需要转成的格式如下图: sql语句如下: , ; 效果如下:

  4. 手把手教你制作微信小程序,开源、免费、快速搞定

    最近做了个"罗孚传车"的小程序 一时兴起,做了一个小程序,将个人收集的同汽车相关的行业资讯和学习资料,分享到小程序中,既作为历史资料保存,又提供给更多的人学习和了解,还能装一下:) ...

  5. Initialize a vector in C++ (5 different ways)

    https://www.geeksforgeeks.org/initialize-a-vector-in-cpp-different-ways/ Following are different way ...

  6. Win10系统的SurfacePro4如何重装系统-1 SurfacePro专用的PE

    下载SurfacePro专用的PE(普通的PE可能不支持触摸屏操作,甚至没法启动Surface,所以务必要重新制作PE),下面提供百度云下载地址,下载之后,双击EXE,会进行检测 链接:https:/ ...

  7. java包名命名规范[【转】

    indi : 个体项目,指个人发起,但非自己独自完成的项目,可公开或私有项目,copyright主要属于发起者. 包名为“indi.发起者名.项目名.模块名.……”. pers : 个人项目,指个人发 ...

  8. Community宣言

    Community宣言 一个幽灵,共产主义的幽灵,在欧洲游荡.为了对这个幽灵进行神圣的围剿,旧欧洲的一切势力,教皇和沙皇.梅特涅和基佐.法国的激进派和德国的警察,都联合起来了. 有哪一个反对党不被它的 ...

  9. numpy中的方差、协方差、相关系数

    一.np.var 数学上学过方差:$$ D(X)=\sum_{i\in [0,n)} ({x-\bar{x}})^2 $$ np.var()实际上是均方差,均方差的意义就是将方差进行了平均化,从而使得 ...

  10. VS2017打开VS2010项目报 “找不到*.xaml”错误

    VS2017打开VS2010项目报 “找不到*.xaml”错误.详细如下: 未处理System.IO.IOExceptionMessage: “System.IO.IOException”类型的未经处 ...