第15章-内部类【扩展】
概述
- 在Java中,还引入了一些其他特点的类
- 内部类,主要是提供一种机制,使得类型封装的耦合度更高、隐藏性更好;比如在某个业务系统中一个HTTP请求的响应中,返回一个与业务响应紧密相关的特定类型的对象,这个类型脱离业务响应不会被使用,就可以定义成业务响应类的内部类
- 类似人体与手臂的关系,手臂不能脱离于人体单独存在,一般就会在描述人体的地方描述手臂,并且手臂一般也不会应用在别的地方,因为只有人体有,其他的生物都叫四肢;这个手臂就相当于是人体的内部类
- 这些类,后续课程中适当的场景,会有应用与讲解,先了解其规则即可
成员内部类
定义于类内部,与属性、方法并列
必须依托于外部类对象,才能创建内部类的对象
在内部类中,可通过外部类名.this.xxx访问外部类对象的属性与方法
应用相对较少,了解即可
应用实例
实例1,定义并使用成员内部类
package com.bjpowernode.demo;
/**
* 内部类示例,成员内部类
*/
public class OuterClass {
//外部类属性
public String outerName;
//定义成员内部类
public class InnerClass {
//内部类属性
public String innerName;
/**
* 内部类方法
*/
public void innerMethod() {
//访问外部类属性,方式:外部类名.this.属性名
System.out.println("外部类对象outerName属性值:" + OuterClass.this.outerName);
//访问内部类属性
System.out.println("内部类对象innerName属性值:" + this.innerName);
}
}
/**
* 入口方法
*
* @param args
*/
public static void main(String[] args) {
//定义外部类对象
OuterClass outerClass = new OuterClass();
outerClass.outerName = "外部名称";
//使用内部类,需要依托外部类对象,才能创建内部类对象
InnerClass innerClass = outerClass.new InnerClass();
//设置内部类属性
innerClass.innerName = "内部名称";
//调用内部内方法
innerClass.innerMethod();
}
}
静态内部类
定义于类内部,与属性、方法并列
类前加static修饰,类似于静态属性和静态方法
不再依托外部类对象,只依托于外部类的类型,来创建对象
有一些业务场景中,某个类对象会跟随另外一个类对象产生而产生;比如登录类中的登录用户详细信息
比如后续集合中的Map.Entry接口,就是Map接口的一个内部接口
应用实例
实例1,定义并使用静态内部类
package com.bjpowernode.demo;
/**
* 内部类示例,静态内部类
*/
public class OuterClass {
//外部类属性
public String outerName;
//定义静态内部类
public static class InnerClass {
//内部类属性
String innerName;
/**
* 内部类方法
*/
public void innerMethod() {
//访问内部类属性,没办法访问外部类普通属性,因为没有外部类对象
System.out.println("内部类对象innerName属性值:" + this.innerName);
}
}
/**
* 入口方法
*
* @param args
*/
public static void main(String[] args) {
//使用静态内部类,需要依托外部类,才能创建内部类对象
InnerClass innerClass = new OuterClass.InnerClass();
//设置内部类属性
innerClass.innerName = "内部名称";
//调用内部内方法
innerClass.innerMethod();
}
}
【练习】
- 练习应用实例内容,完成代码编写;重点练习静态内部类
局部内部类
定义于方法中,只在方法所在作用域中有效
应用相对较少,了解即可
应用实例
实例1,定义并使用局部内部类
package com.bjpowernode.demo;
/**
* 内部类示例,局部内部类
*/
public class OuterClass{
/**
* 生成数据
*/
public void generateData() {
//定义局部内部内,辅助生成数据,该类只在当前方法有效,且不能有访问修饰符
class GenerateUtil {
//URL前缀
String urlPrefix;
public String getUrlPrefix() {
return urlPrefix;
}
public void setUrlPrefix(String urlPrefix) {
this.urlPrefix = urlPrefix;
}
//获取完整URL
public String getFullURL(String path) {
return this.urlPrefix + path;
}
}
//使用局部内部类
GenerateUtil generateUtil = new GenerateUtil();
generateUtil.urlPrefix = "http://www.bjpowernode.com";
String fullUrl = generateUtil.getFullURL("/api/account/login");
System.out.println("完整URL:" + fullUrl);
}
/**
* 入口方法
*
* @param args
*/
public static void main(String[] args) {
//使用具有局部内部类的方法
OuterClass outerClass = new OuterClass();
outerClass.generateData();
}
}
匿名内部类
当某个类的定义时,具备如下两个特点,可使用匿名内部类
- 该类只在某个业务点使用,后续无需重复使用
- 该类将从已有的类、接口派生(继承),即具备父类
应用广泛,在后续课程的函数式编程、项目应用中,都会使用
应用实例
应用实例1,使用抽象类定义匿名类;如:生物学家发现了一个新的动物物种,需要描述一次其特性并使用一次,可基于抽象类(普通类也一样)定义匿名类
抽象类
package com.bjpowernode.demo;
/**
* 动物类,【抽象类】
*/
public abstract class Animal {
//名称
private String name;
//getter/setter,同时也是【普通方法】(非抽象方法),有具体实现
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 吃东西,【抽象方法】,没有具体实现
* @param foodName 食物名称
*/
public abstract void eatFood(String foodName);
/**
* 发声,【抽象方法】,没有具体实现
*/
public abstract void sound();
}匿名类
package com.bjpowernode.demo;
/**
* 动物测试类
*/
public class AnimalTest {
/**
* 入口方法
* @param args
*/
public static void main(String[] args) {
//定义匿名类,定义一个未知动物
Animal anonymous = new Animal() {
@Override
public void eatFood(String foodName) {
System.out.println("未知动物" + this.getName() + "吃了" + foodName);
}
@Override
public void sound() {
System.out.println("未知动物" + this.getName() + "在叫,シ王;忹...");
}
};
//使用匿名类
anonymous.setName("火星二号");
anonymous.eatFood("料-->炓");
anonymous.sound();
}
}
应用实例2,使用接口定义匿名类
接口
package com.bjpowernode.demo;
/**
* 工具
*/
public interface ITool {
/**
* 使用工具
* @param toolName 工具名称
*/
void userTool(String toolName);
}匿名类
package com.bjpowernode.demo;
/**
* 工具测试类
*/
public class ToolDemo {
/**
* 入口方法
*
* @param args
*/
public static void main(String[] args) {
//定义匿名类,定义一个未知工具使用
ITool anonymous = new ITool() {
@Override
public void userTool(String toolName) {
System.out.println("某人使用了工具:" + toolName + ",他眼里都是钉子...");
}
};
//使用匿名类
anonymous.userTool("锤子");
}
}
【练习】
- 练习应用实例内容,完成代码编写;重点练习匿名类
实战和作业
- 【扩展】重构程序,使用第13章重构后的Animal项目,做如下重构
- 使用工具类接口ITool,定义匿名工具类,并测试使用工具方法
- 使用动物类Animal,定义匿名类未知动物类,并测试吃东西、发声方法
- 使用鸟类Bird,定义匿名类未知鸟类,并测试吃东西、发声方法