Java之有名内部类和匿名内部类
Java内部类
定义在外部类中的类就是内部类;内部类的定义是为了更清楚、详细地描述事物。
有名内部类和匿名内部类
Java语言根据内部类是否有类名将内部类分为有名内部类和匿名内部类(没有类名)。
有名内部类及创建对象
public class OutClass{
public void play(){
System.out.println("正在玩耍......");
}
public class Inner{
public void play(){
System.out.println("正在愉快地玩耍......");
}
}
/* public static void main(String[] args){
OutClass outer = new OutClass();
Inner inner = outer.new Inner(); //同类中创建可省略 外部类名
outer.play();
inner.play();
}
*/
}
public class Test{
public static void main(String[] args){
OutClass outer = new OutClass();
OutClass.Inner inner = outer.new Inner();
outer.play();
inner.play();
}
}
正在玩耍......
正在愉快地玩耍......
上例就是一个有名内部类,类名为 Inner,创建内部类对象时的格式为:外部类名.内部类名 对象名 = 外部类对象名.new 内部类名;
还有一种 static 修饰的静态内部类,这时创建对象的格式为: 外部类名.内部类名 对象名 = new 外部类名.内部类名;
public class OutClass{
public void play(){
System.out.println("正在玩耍......");
}
public static class Inner{
public void play(){
System.out.println("正在愉快地玩耍......");
}
}
/*public static void main(String[] args){
OutClass outer = new OutClass();
Inner inner = new OutClass.Inner(); //同理可省略 外部类名
outer.play();
inner.play();
}*/
}
public class Test{
public static void main(String[] args){
OutClass outer = new OutClass();
OutClass.Inner inner = new OutClass.Inner(); //注意:创建方式稍有不同
outer.play();
inner.play();
}
}
正在玩耍......
正在愉快地玩耍......
匿名内部类及创建对象
有些类我们只使用一次就不需要了,如果我们特意为其创建一个类是比较浪费资源的,而匿名内部类就是为了实现这种只使用一次的类。
因为匿名内部类没有类名,所以无法直接创建匿名内部类;定义匿名内部类的同时须直接实例化该类;其语法格式为:
new 父类构造器([参数1],[参数2],...[参数n]){
//匿名内部类类体
}; //注意结尾出必须有 ;
//抽象类
public abstract class Father{
public abstract void work();
}
public class Son{
public static void main(String[] args){
Father father = new Father(){
public void work(){
System.out.println("正在上课......");
}
};
father.work();
}
}
正在上课......
接口在定义匿名构造类的同时也需要将其实例化;其语法格式为:
new 接口(){
//匿名内部类类体
}; //注意结尾出必须有 ;
//接口
public interface IComputer{
void add(int a,int b);
}
public class Test{
public static void main(String[] args){
IComputer iccomputer = new IComputer(){
public void add(int a,int b){
System.out.println(a+b);
}
};
iccomputer.add(1,5);
}
}
注意:
· 匿名内部类一定是接口的实现(该实现只能是一个接口)或类的子类,其中 new 关键字后面的类名或接口名是该匿名内部类继承的父类或实现的接口;
· 匿名内部类中的方法绝对不能是抽象方法;
· 匿名内部类新增的属性和方法不能被上转型对象所调动;只能被非上转型对象方式创建的匿名内部类对象所调用
public interface IComputer{
void add(int a,int b);
}
public class Test{
public static void main(String[] args){
new IComputer(){
public void add(int a,int b){
System.out.println(a+b);
}
public void computer(){
System.out.println("正在计算......");
}
}.computer();
}
}
正在计算......
静态内部类和非静态内部类
根据类是否有 static 修饰词修饰,可将内部类分为静态内部类和非静态内部类,因为以上内部类均为非静态内部类,因此我们下文只说静态内部类;
静态内部类
public class Father{
static String name = "Tom";
String id = "888";
public static void work(){
System.out.println("正在工作......");
}
public void study(){
System.out.println("正在进修......");
}
static{
Son.work(); //调用静态内部类的静态方法
System.out.println(Son.name); //调用静态内部类的静态属性
Son son = new Son(); //创建静态内部类对象
son.study(); //通过创建静态内部类对象调用静态内部类的非静态方法
System.out.println(son.id); //通过创建静态内部类对象调用静态内部类的非静态属性
}
public static class Son{
static String name = "Jim";
String id = "222";
public static void work(){
System.out.println("正在上学......");
}
public void study(){
System.out.println("正在学习......");
}
static{
Father.work(); //调用外部类的静态方法
System.out.println(Father.name); //调用外部类的静态属性
Father father = new Father(); //创建外部类对象
father.study(); //通过创建外部类对象调用外部类的非静态方法
System.out.println(father.id); //通过创建外部类对象调用外部类非静态属性
}
}
public static void main(String[] args){
new Father();
new Father.Son();
}
}
正在工作......
Tom
正在进修......
888
正在上学......
Jim
正在学习......
222
静态内部类可直接调用外部类的静态属性和方法,可以通过创建外部类对象调用外部类非静态属性和方法;
外部类可直接调用静态内部类的静态属性和方法,可以通过创建内部类对象调用静态内部类非静态属性和方法;
注意:静态内部类属于外部类,而不属于外部类对象
内部类特征小结
内部类是一个独立的类,编译后会单独生成一个 .class 文件;如果是有名内部类,则是 外部类名+$+内部类名;如果是匿名内部类,则为 外部类名+$+数字;
普通类、抽象类和接口都可以有内部类(包括有名内部类和匿名内部类);
外部类的访问控制符只能是MT4模拟账户登录教程public 或者是 默认的;但内部类的访问控制符可以是 public、protect、default、private ,还可以用 static 修饰(注意:static不能修饰外部类和接口);
定义在代码块和方法中内部类不能用访问控制符修饰,也不能用 static 修饰;
内部类可以访问外部类所有访问权限的成员变量。
内部类的定义:
在一个外部类中定义的类称为内部类。
内部类的分类:
按是否有名字:有名内部类和匿名内部类。
按是否有static:静态内部类和非静态内部类。
有名内部类:
创建形式如下:
public class Body {
public class Heart{
void work() { //该类为有名内部类,在普通类Heart内部。
System.out.println("正在跳动");
}
}
}
匿名内部类:
1、创建
因为创建对象需要有类名,匿名内部类没有类名,所以匿名内部类定义的时候和创建对象一起定义。
创建形式如下:
new 父类构造器([参数列表])|接口(){
匿名内部类类体
};
Object object = new Object() { //object为匿名内部类的对象。
};
2、特点
① 匿名内部类是普通类的子类:
Object object = new Object() { //此时匿名内部类是Object的子类,而与在哪个类中创建无关。
};
② 匿名内部类是抽象类的子类:
Test1.java
public abstract class Test1 {
public abstract void eat();
}
Test.java
public class Test {
public static void main(String[] args) {
Test1 test = new Test1()
{
public void eat() {
System.out.println("吃");
}
};
}
}
③ 匿名内部类是接口的实现类:
Test1.java
public interface Test1 {
void eat();
}
Test.java
public class Test {
public static void main(String[] args) {
Test1 test = new Test1()
{
public void eat() {
System.out.println("吃");
}
};
}
}
④ 匿名内部类不能是抽象类:
如果匿名内部类是抽象类,则其必须有子类,但是因为匿名内部类没有名字,没有子类,所以匿名内部类不能是抽象类。
共同特点:
1、无论是匿名内部类还是有名内部类,javac都会产生一个独立的class文件,编译之后内部类会被编译成独立的.class文件:
① 如果该内部类为有名内部类,则有名内部类字节码文件名为:
② 如果为匿名内部类,则匿名内部类字节码文件名为(最后加的数字):
2、如果直接在类中定义内部类,则其使用方式与成员变量类似:
Body body = new Body();
System.out.println(body.age);
Heart heart = body.new Heart(); //增加父类变量来调用。
heart.work();
3、外部类或外部接口 public 默认的;但是直接在类中定义的内部类,可以有public ~private。
public class Test {
private class Test01
{
}
public static void main(String[] args) {
}
}
4、如果在内部类中使用局部变量的值,则:JDK8.0及+可以不适用final修饰,8.0以前必须使用fianl。
public class Test {
public static void main(String[] args) {
int age =12; //如果是8.0以前必须在int前面加上fianl。
Test1 test = new Test1()
{
public void eat() {
System.out.println("吃"+age);
}
};
}
}
————————————————
原文链接:https://blog.csdn.net/qq_44971038/article/details/102798027
最新文章
- Servlet使用注解标注监听器(Listener)
- Greenplum(GP)常见问题,注意事项
- Ubuntu 14.04 LTS Server 无法挂载光盘 启动initramfs等问题
- swiper组件实现向上翻页时缩小
- Bootstrap——Jumbotron编写
- vb6如何将MSHFlexGrid控件中的内容导出为Excel
- 用Cornerstone配置SVN
- phpMyAdmin 多个跨站脚本漏洞
- python 杂记
- 使用spool命令从Oracle导出数据
- 学生管理系统(list)
- 解决phpmyadmin-1800秒超时链接失效问题
- hadoop-1.1.0 rpm + centos 6.3 64虚拟机 + JDK7 搭建分布式集群
- 第2章Zabbix基础进阶
- ORA-00904:标识符无效
- Asterisk 11 chan_sip.c: Failed to authenticate device 看不到IP的问题
- 自学Zabbix9.2 zabbix网络发现规则配置详解+实战
- P3806 【模板】点分治1(CDQ分治)
- [实战]MVC5+EF6+MySql企业网盘实战(4)——上传头像
- 学习 TList 类的实现[1]
热门文章
- 【leetcode】421. Maximum XOR of Two Numbers in an Array
- PHP排序函数:sort()、rsort()、asort()、arsort()、ksort()、krsort()
- 工程师技术(六):Linux工程师 综合测试
- paper 140:TLD视觉跟踪算法(超棒)
- CDN(Content Delivery Network)内容分发网络
- 【Shiro】四、Apache Shiro授权
- 2019ccpc秦皇岛/Gym102361 F Forest Program 仙人掌上dfs
- PHP面试 MySQL创建高性能索引考点
- jquery中attr方法和prop方法的区别
- 8. Jmeter导入jar包