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 )就是定义在另外一个类里面的类.与之对应,包含内部类的类被称为外部类. 问:那为什么要将一个类定义在另一个类里面呢?清清爽爽的独立的一个类多 ...
随机推荐
- 821. 字符的最短距离 c++实现方法
1.题目描述 给定一个字符串 S 和一个字符 C.返回一个代表字符串 S 中每个字符到字符串 S 中的字符 C 的最短距离的数组. 示例 1: 输入: S = "loveleetcode&q ...
- selenium之 文件上传所有方法整理总结【转】
本文转自:https://blog.csdn.net/huilan_same/article/details/52439546 文件上传是所有UI自动化测试都要面对的一个头疼问题,今天博主在这里给大家 ...
- 超图不支持JPEG格式的WMTS服务
就目前面而言,超图不支持JPEG格式的WMTS服务,只支持PNG格式的. <本篇完>
- 发现2017年最好的CSS框架
如今,无数的框架出现在定期而少数人喜欢自助,Foundation和angular.js主宰了整个世界的发展.CSS代表用于描述HTML(或XML)文档表示的样式表语言.一个框架被定义为一个包,它由一组 ...
- Rabbit五种消息队列学习(一) – 总述
RabbitMQ支持五种消息传递类型,分别如下图所示: 上图中显示6中消息队列分别为: 1.简单队列 一个生产者将消息放到队列中,一个消费者监听队列 2.工作队列(Work queues) 一个生产者 ...
- css3 box-shadow 使用方法详解
其用法为: 代码如下 复制代码 box-shadow: x-offset y-offset blur spread color inset; 上述六个参数含义依次是水平方向的偏移(正值向右偏移,负值 ...
- 检查linux的磁盘空间占用
先初步看看哪个目录占用最大$ df -h 然后细看遍历某目录的占用情况:$ sudo du -a /data | sort -nr | less(单位是KB)
- MYSQL数据库高可用方案探究
MySQL作为最关键的应用数据存储中心,如何保证MySQL服务的可靠性和持续性,是我们不得不细致考虑的一个问题.当master宕机的时候,我们如何保证数据尽可能的不丢失,如何保证快速的获知master ...
- 通过inotify实现反调试
1.inotify linux下inotify可以实现监控文件系统事件(打开,读写删除等),inotify最常见的api有以下几个: inotify_init:用于创建一个 inotify 实例的系统 ...
- mui 浏览器一样自动缩放
<!doctype html> <html> <head> <meta charset="UTF-8"> <title> ...