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. iOS链接库的冲突

    最近在打包的时候,遇到一个坑.特此记录一下 起因是发现 Unity 5.4 版本,使用c#写的下载,下载速度无法突破 2M/s,同样的网络,后来横向对比使用原来 Cocos2d 开始的游戏,可以达到 ...

  2. shell字符串的用法

    shell字符串的用法 注意:shell4.2和shell4.1会有差别,较低版本的shell可能不支持某些功能 获取字符串长度:${#string} 获取子串: 注:(左边的第一个字符是用 0 表示 ...

  3. CentOs7 HP找回root密码

    linuxman本人尝试了两种方式修改密码,只有一种成功.现展示如下第一种:成功1. 在启动界面选择  centos linux, with linux***.x86_642. 按 e 键进入编辑模式 ...

  4. cookie 跨域解决方法

    1.Nginx 正向和反向代理的区别 正向代理和反向代理的区别:正向代理隐藏真实客户端,反向代理隐藏真实服务端,图示: 2.cookie跨域问题 因为cookie存在跨域问题,其中一个解决方法是,设置 ...

  5. PHP异步扩展Swoole笔记(1)

    安装Swoole扩展 通过pecl安装, 系统中最好已经有http2依赖, 如果是Ubuntu, 可以直接通过apt安装nghttp2, 如果是Centos或者需要自己编译, 在Github下载ngh ...

  6. ORA-12514 TNS:LISTENER DOES NOT CURRENTLY KNOW OF SERVICE REQUESTED IN CONNE

    对比Oracle服务器地址,端口号,还有实例名(也就是服务名).修改tnsnames.ora  在Oracle客户端的安装目录底下. 然后用sqlplus [用户名]/[密码]@[服务命名] 服务命名 ...

  7. 关于TF(词频) 和TF-IDF(词频-逆向文件频率 )的理解

    ##TF-IDF TF(词频):  假定存在一份有N个词的文件A,其中‘明星‘这个词出现的次数为T.那么 TF = T/N; 所以表示为: 某一个词在某一个文件中出现的频率. TF-IDF(词频-逆向 ...

  8. phpexcel 导入超过26列、处理时间格式

    见地址:http://www.thinkphp.cn/topic/33376.html excel处理时间: https://blog.csdn.net/xqd890608/article/detai ...

  9. 【PHP】解析PHP中的函数

    目录结构: contents structure [-] 可变参数的函数 变量函数 回调函数 自定义函数库 闭包(Closure)函数的使用 在这篇文章中,笔者将会讲解如何使用PHP中的函数,PHP是 ...

  10. Atitit s2018.5 s5 doc list on com pc.docx  v2

    Atitit s2018.5 s5  doc list on com pc.docx  Acc  112237553.docx Acc Acc  112237553.docx Acc baidu ne ...