java 内部类、匿名内部类
一:内部类
1:什么是内部类?
大部分时候,类被定义成一个独立的程序单元。在某些情况下,也会把一个类放在另一个类的内部定义,这个定义在其他类内部的类就被称为内部类(有些地方也叫做嵌套类),包含内部类的类也被称为外部类(有些地方也叫做宿主类)
我们先创建一个基本的内部类结构:
class Outer{//外部类
//内部类
class Inner{ }
}
2:内部类的划分
内部类分为成员内部类和局部内部类。内部类也会生成.class文件。
2.1: 成员内部类
定义在外部类中的成员位置,与类中的成员变量相似,可通过外部类对象进行访问。
内部类可以使用外部类的成员,包括私有成员。但是外部类要使用内部类的成员,必须建立内部类变量。
2.2: 局部内部类(比较少用)
定义:在方法里面有一个内部类。
只有在内部类所属的方法中创建内部类对象,方可访问局部内部类。而测试类中只需要创建外部类对象,然后调用外部类方法即可。
3:例子
import java.util.HashMap; public class Parcell { private HashMap<String, String> testMap = new HashMap<String, String>(); class Contents {
// 返回一个外部类的引用.
public Parcell ParcellRef = Parcell.this;
} class Destination {
public void putSomethingInMap() {
testMap.put("hello", "world");
System.out.println(testMap.get("hello"));
} } public Destination to() {
return new Destination();
} public Contents contents() {
return new Contents();
} public void ship(String dest) {
Contents c = new Contents();
Destination d = new Destination();
} public static void main(String[] args) {
Parcell p = new Parcell();
Parcell.Contents c = p.contents();
Parcell.Destination d = p.to();
d.putSomethingInMap();
Parcell.Contents c1 = p.new Contents();
} }
内部类的语法介绍
(1)普通内部类持有一个指向外部类的引用。要创建普通内部类,一定要先创建外部类。
(2)普通内部类就像人体的心脏一样,能够随意访问外部类的任意成员变量。
(3)在内部类中可以通过“外部类类名.this”的方式返回一个指向外部类实例的引用.如Parcell.this
(4)在外部类的static方法中若要创建内部类对象,则需要通过“外部类类名.new XXX()”的方式来创建。
(5)普通内部类中不能拥有静态成员变量。静态内部类中可以拥有静态成员变量。也可以拥有非静态成员变量。但是静态内部类不能访问外部类中非静态的成员变量。而普通内部类可以访问外部类的静态成员变量。
为什么static方法中需要p.new XXX()的方式而非static方法中我们直接new 内部类名 就可以创建一个对象了呢?
如果你有这样的疑问请再看看第一条,一定可以想明白的。
4.作用
1)更好的封装性
2)内部类成员可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,但外部类不能访问内部类的实现细节,例如内部类的成员变量
3)匿名内部类适合用于创建那些仅需要一次使用的类
体外话:静态内部类
Java里面static一般用来修饰成员变量或函数。但有一种特殊用法是用static修饰内部类,普通类是不允许声明为静态的,只有内部类才可以。被static修饰的内部类可以直接作为一个普通类来使用,而不需实例一个外部类。
静态内部类的特点:
1.非静态内部类中不允许定义静态成员
2.外部类的静态成员不可以直接使用非静态内部类
3.静态内部类,不能访问外部类的实例成员,只能访问外部类的类成员
二:匿名内部类
匿名内部类使用最频繁的场合就是在创建线程的时候。
程序清单2-1:
public class Demo { public void test(String title) {
Thread thread = new Thread(new Runnable() { @Override
public void run() {
// title = "我不要吃鸡";
// 改变时会提示错误
// 在封闭范围中定义的局部变量必须是final的。
System.out.println(title);
}
});
thread.start();
} public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Demo demo = new Demo();
demo.test("我要吃鸡" + i);
}
} }
new Thread()
可以接收一个实现了Runnable接口类型的对象,这个对象要怎么创建呢?可以通过匿名内部类的形式来创建——new Runnable() {public void run(){......}}
——这段简短的代码等同于:// 实现Runnable接口
class MyRunnable implements Runnable { @Override
public void run() { }
} // 向上转型
Runnable myRunnable = new MyRunnable();
匿名内部类的好处就在于不仅节省了定义实现类的过程,还能够自动向上转型。
在程序清单2-1中,test()方法还有一个参数title,JDK1.8之前,编译器要求它必须是final类型的。但JDK1.8之后,如果我们在匿名内部类中需要访问局部变量,那么这个局部变量不再需要用final
关键字修饰了。
但如果想要在匿名内部类中改变局部变量的值,编译器就会提醒你不能这样做,它会提示:“在封闭范围中定义的局部变量必须是final的。”
另一个关于匿名内部类的例子:
开发中,最常用到的内部类就是匿名内部类了。以接口举例,当你使用一个接口时,似乎得做如下几步操作。
1、定义子类
2、重写接口中的方法
3、创建子类对象
4、调用重写后的方法
我们的目的,最终只是为了调用方法,那么能不能简化一下,把以上四步合成一步呢?匿名内部类就是做这样的快捷方式。
条件
匿名内部类必须继承一个父类或者实现一个父接口。
格式
new 父类名或者接口名(){
// 方法重写
@Override
public void method() {
// 执行语句
}
};
使用方式
以接口为例,匿名内部类的使用,代码如下:
定义接口:
public abstract class FlyAble{
public abstract void fly();
}
创建匿名内部类,并调用:
public class InnerDemo {
public static void main(String[] args) {
/*
1.等号右边:是匿名内部类,定义并创建该接口的子类对象
2.等号左边:是多态赋值,接口类型引用指向子类对象
*/
FlyAble f = new FlyAble(){
public void fly() {
System.out.println("我飞了~~~");
}
}; //调用 fly方法,执行重写后的方法
f.fly();
}
}
通常在方法的形式参数是接口或者抽象类时,也可以将匿名内部类作为参数传递。代码如下:
public class InnerDemo2 {
public static void main(String[] args) {
/*
1.等号右边:定义并创建该接口的子类对象
2.等号左边:是多态,接口类型引用指向子类对象
*/
FlyAble f = new FlyAble(){
public void fly() {
System.out.println("我飞了~~~");
}
};
// 将f传递给showFly方法中
showFly(f);
}
public static void showFly(FlyAble f) {
f.fly();
}
}
以上两步,也可以简化为一步,代码如下:
public class InnerDemo3 {
public static void main(String[] args) {
/*
创建匿名内部类,直接传递给showFly(FlyAble f)
*/
showFly( new FlyAble(){
public void fly() {
System.out.println("我飞了~~~");
}
});
} public static void showFly(FlyAble f) {
f.fly();
}
}
为什么需要内部类?
Java的内部类让我很容易的想起来JavaScript的闭包,闭包就是定义在一个函数内部的函数——这听起来和Java的内部类定义一样一样的。本质上,闭包是将函数内部与函数外部连接起来的桥梁。内部类一样,它是将内部类与外部类连接起来的桥梁。
来看看什么是闭包吧:
function wanger() {
var age = 30;
function know() {
console.log(age);
}
} wanger();
// 控制台输出30
除此之外,内部类最引人注意的原因是:
内部类可以独立地继承一个抽象类或者实现一个接口,无论外部类是否也这样做了,对内部类都没有影响。
java 内部类、匿名内部类的更多相关文章
- 【Java入门提高篇】Day8 Java内部类——匿名内部类
今天来看看另一个更加神奇的类--匿名内部类. 就像它的名字表示的那样,这个类是匿名的,用完之后,深藏功与名,就像扫地僧那样默默潜藏于深山之中.匿名内部类不仅没有名字,连class关键字都省掉了,而且匿 ...
- java内部类和匿名内部类
内部类即是包含在类里面的又一个类. java内部类分为: 成员内部类.静态嵌套类.方法内部类.匿名内部类 . 内部类的共性 (1).内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.clas ...
- Java内部类小程序(成员内部类,静态内部类,匿名内部类)
/** * 测试java内部类(成员内部类,静态内部类,匿名内部类) * 局部内部类不常用,就不写了. * @package :java05 * @author shaobn * @Describe ...
- Java内部类详解
Java内部类详解 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法.今天我们就 ...
- 黑马----JAVA内部类
黑马程序员:Java培训.Android培训.iOS培训..Net培训 黑马程序员--JAVA内部类 一.内部类分为显式内部类和匿名内部类. 二.显式内部类 1.即显式声明的内部类,它有类名. 2.显 ...
- java 内部类 *** 最爱那水货
注: 转载于http://blog.csdn.net/jiangxinyu/article/details/8177326 Java语言允许在类中再定义类,这种在其它类内部定义的类就叫内部类.内部类又 ...
- [转] Java内部类详解
作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置 ...
- java内部类的作用分析
提起Java内部类(Inner Class)可能很多人不太熟悉,实际上类似的概念在C++里也有,那就是嵌套类(Nested Class),关于这两者的区别与联系,在下文中会有对比.内部类从表面上看,就 ...
- 9)Java内部类(Inner Class)
内部类:不可以有静态数据,静态方法或者又一个静态内部类 内部类的优点:隐藏类的细节,内部类可以声明为私有.内部类可以访问外部类的对象(包括private) 静态内部类:可以有静态数据,静 ...
- JAVA内部类(转)
源出处:JAVA内部类 在java语言中,有一种类叫做内部类(inner class),也称为嵌入类(nested class),它是定义在其他类的内部.内部类作为其外部类的一个成员,与其他成员一样, ...
随机推荐
- 2016百度之星资格赛 Problem A(前缀积与求逆元)
题意:给出一个字符串,每次询问给出x和y要求算出从x到y的每个字符的(ASCII 码值-28)的值的积(mod9973). 分析:首先的想法肯定是算出每个位置的前缀积,然后只要F[y]/F[x-1]即 ...
- electron之环境安装、启动程序
1.安装node.js 2.安装淘宝镜像 npm install -g cnpm --registry=https://registry.npm.taobao.org 3.安装全局electron n ...
- mysql 给用户设置权限
grant all on wordpress.* to wordpress@'10.0.0.%' identified by 'wordpress'; all 全部权限 ...
- SQL-W3School-高级:SQL FOREIGN KEY 约束
ylbtech-SQL-W3School-高级:SQL FOREIGN KEY 约束 1.返回顶部 1. SQL FOREIGN KEY 约束 一个表中的 FOREIGN KEY 指向另一个表中的 P ...
- as 什么意思?
You can denote particular console messages and variable values as having different types using four ...
- linux简单命令8---用户登录查看命令
---------------------------------------------------------------------------------------------------- ...
- Spring Boot连接MySQL报错“Internal Server Error”的解决办法
报错信息如下: {timestamp: "2018-06-14T03:48:23.436+0000", status: 500, error: "Internal Ser ...
- ES6 javascript 实用开发方法技巧分享
定义变量/常量 ES6 中新增加了 let 和 const 两个命令,let 用于定义变量,const 用于定义常量 两个命令与原有的 var 命令所不同的地方在于,let, const 都是块级作用 ...
- 基于mysqld_multi实现MySQL多实例配置
环境: 操作系统 CentOS7.5(已安装MySQL) 主机名 localhost 本机安装路径为 /usr/local/mysql 实验初始配置:所有主机关闭防火墙与selinux [ro ...
- 《剑指offer》Q13-18 (牛客10.13)
目录 Q13 调整数组顺序使奇数位于偶数前 Q14 链表中倒数第k个结点 Q15 反转链表 Q16 合并两个有序链表 Q17 树的子结构 Q18 二叉树的镜像 Q13 调整数组顺序使奇数位于偶数前 输 ...