Java - 提高(7) - 内部类

【推荐100个unity插件之24】实现2d交互式草树叶和随风飘动的效果——pixelgraphics插件 【推荐100个unity插件之23】实现2d交互式草树叶和随风飘动的效果——pixelgraphics插件 阅读详情

内部类


为什么要使用内部类?
在《Think in java》中有这样一句话:
使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。

在我们程序设计中有时候会存在一些使用接口很难解决的问题,这个时候我们可以利用内部类提供的、可以继承多个具体的或者抽象的类的能力来解决这些程序设计问题。

可以这样说,接口只是解决了部分问题,而内部类使得多重继承的解决方案变得更加完整。


上面的文字可能太枯燥 , 估计大家不太想看..我们用代码看下.

//接口1
public interface Fatcher {
	
}
//接口2
public interface Mother {

}
//子类实现两个接口
public class Son implements Fatcher, Mother {
	
}
//或者这么写,通过内部类来实现
public class Daughter implements Fatcher {

	class Mother_ implements Mother {

	}
	
}
上面是接口,但如果是两个父类或者两个抽象类呢?
子类只能继承一个父类 , 这个时候怎么办呢? 不能继承两个父类呀...
这时候就可以使用内部类了..
通过内部类来继承第二个父类.


其实使用内部类最大的优点在于它能够非常好的解决多重继承问题 , 使用内部类还能够为我们带来如下特性:
1. 内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立
2. 在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类
3. 创建内部类对象的时候并不依赖于外围类对象的创建
4. 内部类是一个独立的实体
5. 内部类提供了更好的封装,除了该外围类,其他类都不能访问


我们看一个最常用到的内部类例子:

File file = new File("");
file.listFiles(new FileFilter() {

@Override
public boolean accept(File pathname) {
	// TODO Auto-generated method stub
	return false;
}
});


下面我们一个一个看看有哪些内部类


内部类基础

当我们创建一个内部类时,他无形中就与外围类有了一种联系,依赖于这种联系,它可以无限制的访问外围类的元素。

public class OuterClass {

	private String name;
	private int age;

	public class InnerClass {

	public InnerClass() {
			name = "cyx";
			age = 10;
	}

	public void display() {
			System.out.println("name : " + getName() + " , age : " + getAge());
	}
	}

	public static void main(String[] args) {
			OuterClass o = new OuterClass();
			OuterClass.InnerClass innerClass = o.new InnerClass();
			innerClass.display();
	}

	public String getName() {
			return name;
	}
	public void setName(String name) {
			this.name = name;
	}
	public int getAge() {
			return age;
	}
	public void setAge(int age) {
			this.age = age;
	}
}
在上面代码中,我们可以看到内部类InnerClass可以对外围类OuterClass的属性进行无缝的访问,尽管是private修饰的。
因为当我们创建某个外围类的内部类对象时,此时内部类对象必定会捕获一个指向那个外围类对象的引用,只要我们在访问外围类的成员时,
就会用这个引用来选择外围类的成员。

其实通过上面的代码我们还看到了如何引用内部类:
引用内部类我们需要指明这个对象的类型,OuterClassName.InnerClassName.
同时如果我们需要创建某个内部类对象,必须利用外部类的对象 通过 .new来创建内部类
OuterClass.InnerClass innerClass = OuterClass.new InnerClass();

同时如果我们需要生成对外部类对象的引用,可以使用OuterClassName.this,这样就能够产生一个正确引用外部类的引用了。
public class OuterClass {

public void display() {
	System.out.println("OuterClass....");
}

public class InnerClass {
	public OuterClass getOuterClass() {
			return OuterClass.this;
	}
}

public static void main(String[] args) {
	OuterClass outer = new OuterClass();
	OuterClass.InnerClass innerClass = outer.new InnerClass();
	innerClass.getOuterClass().display();
}

}
输出:OuterClass....
到这里我们需要明确一点,内部类是个编译时的概念,一旦编译成功,它就与外围类属于两个完全不同的类。
对于一个一个名为OuterClass的外围类和一个名为InnerClass的内部类,在编译成功之后,会出现这样两个class文件:
OuterClass.class和OuterClass$InnerClass.class

这里再提供一个Thinking in Java中提供的例子,体会下内部类的使用:

public class Parcell {

	class Contents {
			private int i = 22;

	public int value() {
			return i;
	}
	}

	class Destination {

	private String label;

	public Destination(String whereTo) {
			label = whereTo;
	}

	String readLabel() {
			return label;
	}

	}

	public void ship(String dest) {
			Contents c = new Contents();
			System.out.println("c.value() : " + c.value());
			
			Destination d = new Destination(dest);
			System.out.println("d.readLabel() : " + d.readLabel());
	}

	public static void main(String[] args) {
			Parcell p = new Parcell();
			p.ship("CYX");
	}

}



在Java中内部类主要分为成员内部类,局部内部类,匿名内部类,静态内部类。


成员内部类
成员内部类是最普通的内部类,它是外围类的一个成员,所以它是可以无限制的访问外围类的所有成员属性和方法,尽管是private的
但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。

在成员内部类中需要注意两点:
1. 成员内部类中不能存在任何static的变量和方法
2. 成员内部类是依附于外围类的,所有只有先创建外围类才能创建内部类

public class OuterClass {

	private String str;

	public void outerDisplay() {
			System.out.println("outerClass...");
	}

	public class InnerClass {

	public void innerDisPlay() {
			// 使用外围类的属性
			str = "chenssy....";
			System.out.println("str : " + str);
			// 调用外围类的方法
			outerDisplay();
	}
	}

	public InnerClass getInnerClass() {
			return new InnerClass();
	}

	public static void main(String[] args) {
			OuterClass outer = new OuterClass();
			OuterClass.InnerClass innerClass = outer.getInnerClass();
			innerClass.innerDisPlay();
	}
}
推荐使用getxxx()来获取成员内部类,尤其是该内部类的构造函数无参数时


局部内部类
有种内部类,它是嵌套在方法和作用域中,对于这个类的使用主要是 应用/解决比较复杂的问题;
想创建一个类来辅助我们的解决方案,但又不想这个类是公共可用的。所以就产生了局部内部类;
局部内部类和成员内部类一样被编译,只是它的作用域发生了改变,它只能在该方法和属性中被使用,出了该方法和属性就会失效。

定义在方法里

public class Parcel {

	public Destionation destionation(String str) {
			class PDestionation implements Destionation {
					private String label;

	private PDestionation(String whereTo) {
			label = whereTo;
	}

	public String readLabel() {
			return label;
	}
	}
	return new PDestionation(str);
	}

	public static void main(String[] args) {

	Parcel p = new Parcel();
	Destionation d = p.destionation("CYX");
	
	}

}
定义在作用域内:

public class Pracel6 {

	private void internalTracking(boolean b) {

	if (b) {

	class TrackingSlip {
			private String id;

	TrackingSlip(String s) {
			id = s;
	}

	String getSlip() {
			return id;
	}
	}

	TrackingSlip ts = new TrackingSlip("cyx");
	String string = ts.getSlip();

	}
	}

	public void track() {
			internalTracking(true);
	}

	public static void main(String[] args) {
			Pracel6 p = new Pracel6();
			p.track();
	}

}


匿名内部类

匿名内部类的特点:
匿名内部类一定是跟在new后面的,用其隐含实现一个接口或一个类,没有类名,根据多态,我们使用其父类名。
因为匿名内部类属于局部类,所以局部类的所有限制对其生效。
匿名内部类是唯一一个无构造方法的类。
匿名内部类在编译时,系统自动起名Out$1.class。
如果一个对象编译时的类型是接口,那么其运行的类型为实现这个接口的类。

直接上实例

public static void main(String[] args) {

	new File("C:/Foxmail 7.2").listFiles(new FileFilter() {

	@Override
	public boolean accept(File pathname) {
		System.out.println(pathname);
		return false;
	}
	});

}

FileFilter本身是一个接口


再来一个栗子

public abstract class Bird {

	private String name;

	public abstract int fly();

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

//------------------------------------

public class Test {

	public void test(Bird bird) {
		System.out.println(bird.getName() + "能够飞 " + bird.fly() + " 米");
	}

	public static void main(String[] args) {
		Test test = new Test();
		test.test(new Bird() {
			@Override
			public int fly() {

				return 1000;
			}

			@Override
			public String getName() {
				return "大雁";
			}
		});
	}

}
在Test类中,test()方法接受一个Bird类型的参数,同时我们知道一个抽象类是没有办法直接new的,我们必须先有实现类才能new出
它的实例。所以在main方法中直接使用匿名内部类来创建一个Bird实例。

由于匿名内部类不能是抽象类,所以他必须要实现它的抽象父类或者接口里面所有抽象方法。

其实 匿名内部类是可以拆分的...
举个栗子:

这个是实现了FileFilter的实现类



然后是具体调用
1: 使用匿名内部类
2:没有使用匿名内部类,从代码角度来看,使用匿名内部类能够简化代码(少写类)



对于匿名内部类的使用它存在一个缺陷,就是它仅能被使用一次,创建匿名内部类时它会立即创建一个该类的实例,该类的定义
会立即消失,所以匿名内部类时不能够被重复使用。

注意事项:
a. 使用匿名内部类时,我们必须继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。(??)
b. 匿名内部类中是不能定义构造函数的。
c. 匿名内部类中不能存在任何静态成员变量和静态方法
d. 匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效
e. 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象/方法。


匿名内部类的优点:
a. 可以使命名变得简洁,使代码更加紧凑,简洁,封装性比内部类更优。
b. 一个类用于继承其他类或是实现接口,无需增加其他的方法,只是对继承方法实现,覆盖。



静态内部类
关键字static中提到static可以修饰成员变量、方法、代码块,其实它还可以修饰内部类,使用static修饰的内部类我们称之为静态内部类,
不过更喜欢称之为"嵌套内部类"

静态内部类与非静态内部类之间存在一个最大的区别:
我们知道非静态内部类在编译完成之后会隐含的保存着一个引用,该引用是指向创建它的外围类,但是静态内部类却没有。
没有这个引用就意味着:
1. 它的创建是不需要依赖于外围类的。
2. 它不能使用任何外围的非static成员变量和方法。

来个栗子体会一下

/**
 * @author CYX
 * @create 2017-05-19-9:45
 */

public class OuterClass {

	private String sex;
	public static String name = "chenssy";

	/**
	 * 静态内部类
	 */
	static class InnerClass1 {

		public static String _name1 = "chenssy_static";

		public void display() {

			//静态内部类只能访问外围类的静态成员变量和方法,不能访问外围类的非静态成员变量和方法.
			System.out.println("InnerClass1 OuterClass name : " + name);
		}
	}

	/**
	 * 非静态内部类
	 */
	class InnerClass2 {
		public String _name2 = "chenssy_inner";

		public void display() {
			System.out.println("InnerClass2 OuterClass name : " + name);
		}

	}

	/**
	 * 外围方法
	 */
	public void display() {

		//外围类访问静态内部类:内部类
		System.out.println("InnerClass_1._name1 :" + InnerClass1._name1);
		//静态内部类,可以直接创建实例不需要依赖于外围类
		new InnerClass1().display();

		//非静态内部的创建的需要依赖于外围类
		OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();
		//访问非静态内部类的成员变量需要使用非静态内部类的实例
		System.out.println("inner2._name2 : " + inner2._name2);
		inner2.display();

	}

	public static void main(String[] args) {
		OuterClass outerClass = new OuterClass();
		outerClass.display();
	}

}

输出:
		InnerClass_1._name1 :chenssy_static
		InnerClass1 OuterClass name : chenssy
		inner2._name2 : chenssy_inner
		InnerClass2 OuterClass name : chenssy
		


参考资料:

http://www.cnblogs.com/chenssy/ 

《Thinking in Java》

【DRAM存储器五十七】LPDDR5介绍--read DQ training和WCK DQ training 简述LPDDR5训练中的读写DQ训练 阅读详情

相关推荐

用AI+Playwright实现零代码UI自动化测试:以登录页面为例的实战指南

本文详细介绍了如何利用AI与Playwright结合实现零代码UI自动化测试,特别以登录页面为例进行实战演示。通过自然语言描述生成测试脚本,大幅降低技术门槛,提升测试效率,并支持跨浏览器验证。适合非技术人员快速上手专业级自动化测试。

weixin_28842269的博客 402

【Java入门提高篇】Day7 Java内部类——局部内部类

 今天介绍第二种内部类——局部内部类。   局部内部类是什么?顾名思义,那就是定义在局部内部的类(逃)。开玩笑的,局部内部类就是定义在代码块、方法体内、作用域(使用花括号“{}”括起来的一段代码)内的类。局部内部类有以下特性: 局部内部类只能在代码代码块、方法体内和作用域中使用。 局部内部类同样可以无限制调用外部类的方法和属性。 可以使用abstract修饰,声明为抽象类。   举个栗子...

91

Laravel 结合 jwt-auth 实现无状态 API 认证(实战解析)

本文详细解析了如何在Laravel框架中结合jwt-auth实现无状态API认证,包括JWT的优势、环境搭建、Token签发与刷新、API路由保护等实战内容。通过具体代码示例和优化技巧,帮助开发者高效解决跨域认证问题,提升系统安全性。

weixin_29315569的博客 210

局部内部类 java_【Java入门提高篇】Day7 Java内部类——局部内部类

今天介绍第二种内部类——局部内部类。局部内部类是什么?顾名思义,那就是定义在局部内部的类(逃)。开玩笑的,局部内部类就是定义在代码块、方法体内、作用域(使用花括号“{}”括起来的一段代码)内的类。局部内部类有以下特性:局部内部类只能在代码代码块、方法体内和作用域中使用。局部内部类同样可以无限制调用外部类的方法和属性。可以使用abstract修饰,声明为抽象类。举个栗子:public classOu...

weixin_31263231的博客 163

华硕ROG玩家国度安装Ubuntu双系统避坑指南:安全启动密钥那些事儿

本文详细解析了在华硕ROG玩家国度设备上安装Ubuntu双系统时,如何正确处理BIOS中的安全启动(Secure Boot)与密钥管理,避免常见的引导失败和Windows系统无法启动问题。指南提供了从数据备份、启动盘制作到BIOS精细设置(如将OS Type改为Other OS而非简单关闭Secure Boot)以及分区规划的完整流程,确保两个系统都能稳定共存。

weixin_29219189的博客 754

ABAP代码使用OAuth2.0 Client Credential调用外部API

ABAP-OAuth2.0-调用外部API

m0_74015269的博客 1956

以下关于java的内部类_【Java入门提高篇】Day7 Java内部类——局部内部类

今天介绍第二种内部类——局部内部类。局部内部类是什么?顾名思义,那就是定义在局部内部的类(逃)。开玩笑的,局部内部类就是定义在代码块、方法体内、作用域(使用花括号“{}”括起来的一段代码)内的类。局部内部类有以下特性:局部内部类只能在代码代码块、方法体内和作用域中使用。局部内部类同样可以无限制调用外部类的方法和属性。可以使用abstract修饰,声明为抽象类。举个栗子:这里的Inner2类仅仅在O...

weixin_30533377的博客 140

YOLOv5 自定义模型 Android 部署完整指南

本文详细介绍了将YOLOv5模型部署到Android设备的完整流程,包含三个核心部分:首先验证官方模型测试,确保基础环境配置正确;随后进行模型转换,从PyTorch导出ONNX格式并优化,再转换为NCNN格式;最后在Android项目中集成自定义模型,包括文件替换、参数修改和代码适配。教程基于YOLOv5 6.1版本,使用NCNN框架进行移动端推理,涵盖了常见问题解决方案和关键配置要点,为开发者提供了从训练到部署的完整技术路线。

FJN110的博客 591

java 匿名内部类 this_java - 匿名内部类中的this,如何在lambda中获得?

PHP中文网2017-06-23 09:15:262楼取代某些匿名内部类本节将介绍如何使用Lambda表达式简化匿名内部类的书写,但Lambda表达式并不能取代所有的匿名内部类,只能用来取代函数接口(Functional Interface)的简写。先别在乎细节,看几个例子再说。例子1:无参函数的简写如果需要新建一个线程,一种常见的写法是这样:// JDK7 匿名内部类写法new Thread(n...

weixin_39865061的博客 522

【车载以太网】【架构】整体架构与协议标准

车载以太网架构图 应用层:DHCP /SOMEIP/DoIP/XCP/UDPNM 传输层:TCP/IP 网络层:IPv4/IPv6/ARP/ICMP 链路层:IEEE Ethernet MAC+VLAN 物理层:Ethernet PHY: 100BASE-T1/1000BASE-T1/100BASE-Tx

专注汽车软件开发、AutoSAR、车载以太网、SOA、EE架构。 8354

把大表拆成更好用的“小仓库”:SAP HANA 表分区设计、分区裁剪与内存代价全解析

摘要:本文深入解析SAP HANA分区技术的核心价值与实现策略。作为内存数据库的"手术刀",分区通过将逻辑表横向切分为独立物理容器,显著提升并行计算能力与查询效率。重点探讨了三种分区类型(Range、Hash、Round-robin)的适用场景,以及分区裁剪的优化原理与前提条件。特别指出分区设计需要平衡查询模式与数据分布,并揭示了分区对内存占用的双向影响机制:既可能因字典复制增加消耗,也可能因数据纯度提升压缩率。通过电商订单表等实际案例,展示了合理分区如何将分钟级报表优化至秒级响应。文章

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1648

Java 9 新特性 – 内部类的方块操作符

方块操作符 ( <> ) 在 Java 7 中就引入了,目的是为了使代码更可读。 但是呢,这个操作符一直不能在匿名内部类中使用 Java 9 修正了这个问题,就是可以在匿名内部类中使用方块操作符了,在匿名类大行其道的今天,这才叫优化了阅读体验... 我们来看看一段 Java 9 之前的代码 ...

heima201907的博客 128

【WRF-DART第一期】WRF/DART概述

【WRF-DART第一期】WRF/DART概述

WW、forever的博客 107

java 8代码 改 java7_春季-将Java 8代码移植到Java 7

是否可以将这段代码从Java 8移植到Java 7?protected UserDetailsService userDetailsService() {return (username) -> {User u = crmService.findUserByUsername(username);return new org.springframework.security.core.user...

weixin_34286711的博客 177

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

详解 Java 内部类

前言 内部类在 Java 里面算是非常常见的一个功能了,在日常开发中我们肯定多多少少都用过,这里总结一下关于 Java 中内部类的相关知识点和一些使用内部类时需要注意的点。 从种类上说,内部类可以分为四类:普通内部类、静态内部类、匿名内部类、局部内部类。我们来一个个看: 普通内部类 这个是最常见的内部类之一了,其定义也很简单,在一个类里面作为类的一个字段直接定义就可以了,例: pub...

指点 6万+

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

java内部类

1、局部内部类就是定义在外部类的局部位置上,比如方法内,并且有类名。class Outer {//外部类public void show() {//方法class Inter {//局部内部类} } }2、局部内部类可以访问外部类的所有成员,包括私有成员。class Outer {//外部类//私有变量private void method1() {}//私有方法public void show() {//方法class Inter {//局部内部类//调用外部类私有变量。

qq_65501197的博客 1430

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Java中的内部类详解

内部类(Inner Class)是定义在另一个类内部的类。Java中的内部类就像是外部类的一个成员,它可以访问外部类的所有成员变量和方法,即使它们被声明为private。内部类的主要特点可以访问外部类的所有成员(包括私有成员)能够实现"多重继承"的效果提高了封装性可以更好地组织代码结构提高封装性:内部类可以隐藏实现细节访问外部类的私有成员:增强了类之间的联系实现回调机制:特别是匿名内部类避免多继承问题:通过内部类可以模拟多继承效果选择使用哪种内部类的建议成员内部类静态内部类局部内部类。

qq_38955667的博客 1963

Java 四大内部类总结——局部内部类,匿名内部类,成员内部类,静态内部类

Java 四大内部类总结——局部内部类,匿名内部类,成员内部类,静态内部类

prince0520的博客 3118
上一篇: Java - 提高-源码(6) - HashSet
下一篇: Java - 提高(8) - equals和hashCode
Simba_cheng
博客等级 码龄11年 250粉丝 203原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值