Java中的 内部类(吐血总结)
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
* 注意:
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中的 内部类(吐血总结)的更多相关文章
- Java中的内部类(成员内部类、静态内部类、局部内部类、匿名内部类)
Java中的内部类(成员内部类.静态内部类.局部内部类.匿名内部类) 神话丿小王子的博客主页 我们先看这样一段话:人是由大脑.肢体.器官等身体结果组成.而组成我们人体的心脏它也有自己的属性和行为(血液 ...
- Java 中的内部类
前言 在第一次把Java 编程思想中的内部类这一章撸完后,有点印象.大概知道了什么时内部类,局部内部类,匿名内部类,嵌套内部类.随着时间的推移,自己慢慢的就忘记了,总感觉自己思考的东西不多,于是 看了 ...
- 【转】Java中的内部类和匿名类
Java内部类(Inner Class),类似的概念在C++里也有,那就是嵌套类(Nested Class),乍看上去内部类似乎有些多余,它的用处对于初学者来说可能并不是那么显著,但是随着对它的 ...
- Java学习笔记二十:Java中的内部类
Java中的内部类 一:什么是内部类: (1).什么是内部类呢? 内部类( Inner Class )就是定义在另外一个类里面的类.与之对应,包含内部类的类被称为外部类. (2).那为什么要将一个类定 ...
- Java中的内部类怎么用
一.为什么需要内部类?java内部类有什么好处?为什么需要内部类? 首先举一个简单的例子,如果你想实现一个接口,但是这个接口中的一个方法和你构想的这个类中的一个方法的名称,参数相同,你应该怎么办?这时 ...
- Java中的内部类(回调)
一.内部类的主要作用如下: 1. 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类 2. 内部类的方法可以直接访问外部类的所有数据,包括私有的数据 3. 内部类所 ...
- 【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 ...
- Java中的内部类————以及jdk1.8的lambda表达式
一.内部类学习导图 1>.静态内部类: 使用static修饰符来修饰内部类,则这个内部类就属于外部类本身,而不属于外部类的某个对象.因此使用static修饰的内部类被称为静态内部类. publi ...
- Java基础(十五):Java 中的内部类
问:什么是内部类呢? 答:内部类( Inner Class )就是定义在另外一个类里面的类.与之对应,包含内部类的类被称为外部类. 问:那为什么要将一个类定义在另一个类里面呢?清清爽爽的独立的一个类多 ...
随机推荐
- iOS链接库的冲突
最近在打包的时候,遇到一个坑.特此记录一下 起因是发现 Unity 5.4 版本,使用c#写的下载,下载速度无法突破 2M/s,同样的网络,后来横向对比使用原来 Cocos2d 开始的游戏,可以达到 ...
- shell字符串的用法
shell字符串的用法 注意:shell4.2和shell4.1会有差别,较低版本的shell可能不支持某些功能 获取字符串长度:${#string} 获取子串: 注:(左边的第一个字符是用 0 表示 ...
- CentOs7 HP找回root密码
linuxman本人尝试了两种方式修改密码,只有一种成功.现展示如下第一种:成功1. 在启动界面选择 centos linux, with linux***.x86_642. 按 e 键进入编辑模式 ...
- cookie 跨域解决方法
1.Nginx 正向和反向代理的区别 正向代理和反向代理的区别:正向代理隐藏真实客户端,反向代理隐藏真实服务端,图示: 2.cookie跨域问题 因为cookie存在跨域问题,其中一个解决方法是,设置 ...
- PHP异步扩展Swoole笔记(1)
安装Swoole扩展 通过pecl安装, 系统中最好已经有http2依赖, 如果是Ubuntu, 可以直接通过apt安装nghttp2, 如果是Centos或者需要自己编译, 在Github下载ngh ...
- ORA-12514 TNS:LISTENER DOES NOT CURRENTLY KNOW OF SERVICE REQUESTED IN CONNE
对比Oracle服务器地址,端口号,还有实例名(也就是服务名).修改tnsnames.ora 在Oracle客户端的安装目录底下. 然后用sqlplus [用户名]/[密码]@[服务命名] 服务命名 ...
- 关于TF(词频) 和TF-IDF(词频-逆向文件频率 )的理解
##TF-IDF TF(词频): 假定存在一份有N个词的文件A,其中‘明星‘这个词出现的次数为T.那么 TF = T/N; 所以表示为: 某一个词在某一个文件中出现的频率. TF-IDF(词频-逆向 ...
- phpexcel 导入超过26列、处理时间格式
见地址:http://www.thinkphp.cn/topic/33376.html excel处理时间: https://blog.csdn.net/xqd890608/article/detai ...
- 【PHP】解析PHP中的函数
目录结构: contents structure [-] 可变参数的函数 变量函数 回调函数 自定义函数库 闭包(Closure)函数的使用 在这篇文章中,笔者将会讲解如何使用PHP中的函数,PHP是 ...
- 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 ...