Java面向对象笔记 • 【第8章 内部类和泛型】
全部章节 >>>>
本章目录
8.1 内部类
8.1.1 内部类概述
- 为实现程序设计的需要,需要将一个类放在另一个类的内部定义,定义在其他类内部的类就称为内部类,包含内部类的类也被称为外部类,内部类的作用如下:
- 内部类提供了更好的封装,可以将内部类隐藏在外部类内,不允许同一个包中的其他类访问该类。
- 内部类成员可以直接访问外部类的私有数据,因为内部类作为其外部类成员,同一个类的成员之间可以相互访问。但外部类不能访问内部类的实现细节,如内部类的成员变量。
- 匿名内部类适用于创建那些仅需要一次使用的类。
8.1.2 内部类使用
语法:
public class OutClass{
……
//定义内部类
public class innerClass{
}
}
内部类分为两种:静态内部类和非静态内部类,使用static修饰的内部类称为静态内部类,没有使用static修饰的内部类则称为非静态内部类。
8.1.3 实践练习
8.2 静态内部类
8.2.1 静态内部类的实现
- 使用static修饰的内部类,被称为静态内部类,静态内部类属于外部类本身,而不属于外部类的某个对象。
- 静态内部类可以包含静态成员,也可以包含非静态成员。
- 依据静态成员不能访问非静态成员的规则,静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。即使是静态内部类的实例方法,也不能访问外部类的实例成员,只能访问外部类的静态成员。
示例: 演示静态内部类的定义
public class OutClass {
private int outPro=5;
private static int outPro2=9;
private static class InnerClass{
private static int innerPro=10;//静态内部类中可以定义静态成员
private int innerPro2=100;//静态内部类中的实例属性
public void accessOutPro(){
/*以下代码在编译时出现错误静态内部类无法直接访问外部类的实例成员*/
//System.out.println(outPro);
//可通过外部类实例访问外部类实例属性
System.out.println("外部类实例属性outPro="+new OutClass().outPro);
//访问外部类的静态成员,代码正确
System.out.println("外部类的静态属性outPro2="+outPro2);
}
}
//未完接下一页
}
public class OutClass {
//接上一页
public void accessInnerPro(){
//System.out.println(innerPro);
//以上代码出现错误,应修改为如下形式,即通过类名访问静态内部类的类成员
System.out.println("内部类的静态属性innerPro="+InnerClass.innerPro);
//System.out.println(innerPro2);
//以上代码出现错误,应修改为如下格式
InnerClass ic=new InnerClass();
System.out.println("内部类实例属性innerPro2="+ic.innerPro2);
ic.accessOutPro();//调用静态内部类的实例方法
}
public static void main(String[] args) {
OutClass oc=new OutClass();
oc.accessInnerPro();
}
}
8.2.2 实践练习
8.3 匿名内部类
8.3.1 匿名内部类的实现
匿名内部类适用于仅需要一次使用的类,匿名内部类的语法较为特别,创建匿名内部类时,会立即创建一个该类的实例,创建完毕之后该类的定义会立即消失。
如果匿名内部类需要访问外部类的局部变量,则必须使用final修饰符修饰外部类的局部变量,否则系统将报错。
语法:
new 父类构造器(参数列表)| 实现接口(){
//匿名内部类的类体部分
}
匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类,或实现一个接口。
提醒:匿名内部类的两条规则
- 匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象,因此不允许将匿名内部类定义成抽象类。
- 匿名内部类不能定义构造器,因为匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义实例化初始块,通过实例化初始块来完成构造器需要完成的事情。
示例: 演示匿名内部类的定义
//匿名内部类需要实现的接口
public interface Product {
double getPrice();
String getName();
}
public class Anonymous {
public void execute(Product product){
System.out.println("购买了一个:"+product.getName()+" 花费:"+product.getPrice());
}
public static void main(String[] args) {
Anonymous aym=new Anonymous();
/*调用execute()方法时,需要创建一个Product类型参数,此处传入匿名实现类的实例*/
aym.execute(new Product() {
public double getPrice() {
return 98.29;
}
public String getName() {
return "费列罗巧克力";
}
});
}
}

示例:将匿名内部类更改为内部类
public class Consumer {
public void execute(Product product){
System.out.println("购买了一个:"+product.getName()+" 花费:"+product.getPrice());
}
public class MyProduct implements Product{ //内部类
public double getPrice() {
return 98.29;
}
public String getName() {
return "费列罗巧克力";
}
}
public static void main(String[] args) {
Consumer consumer = new Consumer(); //实例化一个外部类对象
//通过外部类对象创建内部类对象
Product product = consumer.new MyProduct();
consumer.execute(product);
}
}
8.3.2 实践练习
8.4 泛型
8.4.1 泛型概述
没有使用泛型时取出集合元素
List listUser = new ArrayList();
listUser.add(new User(“张三”,20)) ;
User user = (User)listUser.get(0) ; //使用了强制类型转换。
使用泛型时取出集合元素
List<User> listUser = new ArrayList<User>();
listUser.add(new User(“张三”,20)) ;
User user = listUser.get(0) ; //把类型转换交给了编译器
泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
泛型的原理就是参数化类型
- 泛型把类型看做参数,也就是说把所要操作的数据类型看做参数,就像方法的形式参数是运行时传递的值的占位符一样。
- 泛型中的类型变量扮演的角色就如同一个参数,它提供给编译器用来类型检查的信息。
泛型的分类
- 泛型类
- 泛型方法
8.4.2 泛型应用
1、泛型类:就是具有一个或多个类型变量的类。
示例: 定义泛型类并实例化泛型类
public classPair<T>{
private T first
public Pair(T first){this.first=first;}
public void setFirst(T newValue){first=newValue;}
public T getFirst(){return first;}
}
public class PairTest{
public static void main(String[] args){
//用具体的类型替换类型变量就可以实例化泛型类型
Pair<String> pair=new Pair<String>("Hello");
System.out.println("first="+pair.getFirst());
}
}
2、泛型方法:
- 带有参数类型的方法即泛型方法,泛型方法使得该方法能够独立于类而产生变化。
- 泛型方法所在的类可以是泛型类,也可以不是泛型类。
示例:声明一个f(T x)泛型方法,用于返回调用该方法时,所传入的参数类型的类名
class GenericMethod{
//T是泛型类型参数
public <T> void f(T x){
System.out.println(x.getClass().getName());
}
}
public class GenericMethodTest{
public static void main(String[] args){
GenericMethod gm=new GenericMethod();
gm.f(" ");
gm.f(1);
gm.f(1.0f);
gm.f('c');
gm.f(gm);
}
}

3、泛型定义:泛型定义包括泛型类定义和泛型对象定义,其中泛型对象定义的应用最为普遍。
语法:
类名称<具体类> 对象名称 = new 类名称<具体类>();
例如:
List<String> citys = new ArrayList<String>(); //城市列表
List<Address> empAdds = new ArrayList<Address>(); //员工住址列表
Map<String, Emp> empnoToEmp = new HashMap<String, Emp>(); //员工编号到员工映射
示例: 泛型集合List<T>与Map<K,V>应用
List<String> strList=new ArrayList<String>(); //声明泛型集合,该集合元素为String类型
//strList集合中只能添加字符串元素,否则无法通过编译
strList.add("apple");
strList.add("peer");
strList.add("banana");
//strList.add(new Date());此处如果不将其注释,在编译时系统报错
//集合使用泛型后,从集合中获取数据无须强制类型转换
String str=strList.get(strList.size()-1);
//创建Map泛型集合,map的Key为String类型,value为Date类型
Map<String,Date> map=new HashMap<String,Date>();
//向集合中添加数据
map.put("Java", new Date(60000));
map.put("C#", new Date(300000000));
map.put("MySQL", new Date(1000000));
//调用keySet()方法返回装有所有Key值的Set集合
Set<String> keySet=map.keySet();
//通过keySet获取Iterator迭代器
Iterator<String> iter=keySet.iterator();
while(iter.hasNext()){//遍历迭代器
String key=iter.next();
System.out.println("Map["+key+"]="+map.get(key));
}

8.4.3 实践练习
总结:
- 内部类提供了更好的封装,可以将内部类隐藏在外部类内。内部类成员可以直接访问外部类的私有数据,但外部类不能访问内部类的成员变量。
- 使用static修饰的内部类,被称为静态内部类,静态内部类属于外部类本身,而不属于外部类的某个对象。
- 匿名内部类适用于创建那些仅需要一次使用的类,匿名内部类不能是抽象类,不能定义构造器,但是可以通过实例化初始块来完成构造器需要完成的事情。
- 泛型的原理就是参数化类型,泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
Java面向对象笔记 • 【第8章 内部类和泛型】的更多相关文章
- Java面向对象程序设计第9章1-9
Java面向对象程序设计第9章1-9 1. 线程和进程的联系和区别是什么? 联系: 一个进程可以包括多个线程. 区别: 进程: 进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,它是系统 ...
- 20145330《Java学习笔记》第一章课后练习8知识总结以及IDEA初次尝试
20145330<Java学习笔记>第一章课后练习8知识总结以及IDEA初次尝试 题目: 如果C:\workspace\Hello\src中有Main.java如下: package cc ...
- Java面向对象程序设计第14章3-8和第15章6
Java面向对象程序设计第14章3-8和第15章6 3.完成下面方法中的代码,要求建立一个缓冲区,将字节输入流中的内容转为字符串. import java.io.*; public class tes ...
- Java面向对象程序设计第8章3-5
Java面向对象程序设计第8章3-5 3.String类型有什么特点? 一旦赋值,便不能更改其指向的字符对象 如果更改,则会指向一个新的字符对象 不能为null 4.String什么时候进行值比较,什 ...
- Java面向对象程序设计第7章1-8
Java面向对象程序设计第7章1-8 1."程序中凡是可能出现异常的地方必须进行捕获或拋出",这句话对吗? 不对. 异常分两类,runtime异常和非runtime异常. runt ...
- Java面向对象笔记 • 【第3章 继承与多态】
全部章节 >>>> 本章目录 3.1 包 3.1.1 自定义包 3.1.2 包的导入 3.1.3 包的访问权限 3.1.4 实践练习 3.2 继承 3.2.1 继承概述 3 ...
- Java 学习笔记 ------第六章 继承与多态
本章学习目标: 了解继承的目的 了解继承与多态的关系 知道如何重新定义方法 认识java.lang.object 简介垃圾回收机制 一.继承 继承是java面向对象编程技术的一块基石,因为它允许创建分 ...
- Java面向对象笔记 • 【第2章 面向对象进阶】
全部章节 >>>> 本章目录 2.1 成员变量 2.1.1 成员变量与局部变量的区别 2.1.2 成员变量的使用 2.1.3 实践练习 2.2 this关键字 2.2.1 ...
- Java面向对象笔记 • 【第1章 面向对象】
全部章节 >>>> 本章目录 1.1 类和对象 1.1.1 类和对象的概念 1.1.2 类的语法结构 1.1.3 对象的创建和使用 1.1.4 对象和引用 1.1.5 实践 ...
随机推荐
- C++最小内积
Description 向量是几何中的一个重要概念. 考虑两个向量 v1=(x1,x2,...,xn)和v2=(y1,y2,...,yn),向量的内积定义为 x1y1+x2y2+...+xnyn 例如 ...
- How exactly does Google AdWords work?
The key to how Google AdWords works is the Quality Score. Quality Score is generally how well an ad ...
- Output of C++ Program | Set 12
Predict the output of following C++ programs. Question 1 1 #include <iostream> 2 using namespa ...
- System.exit(-1)和return 的区别
对于只有一个单一方法的类或者系统来说是一样的,但是对于含有多个类和方法,且调用关系比较复杂时就不一样了. System.exit(-1)是指所有程序(方法,类等)停止,系统停止运行. return只是 ...
- 【Java】基本语法学习笔记
1.数组 *数组的创建 int[] array = {1,2,3,4,5}; 注意区别于C++ int a[] = (1)两种输出方法 public class number { public sta ...
- 使用 OPC Browser 加载 OPC Server 监测点
1,首先第一步,要连接OPC ,创建好 OPC对象. /// <summary> /// 连接OPC /// </summary> private string OPCIP=1 ...
- vue文件上传及压缩(canvas实现压缩)
// 读取文件结果 afterRead(files) { let that = this; let file = files.file; if (file === undefined) { retur ...
- [Java Web 王者归来]读书笔记2
第二篇 基础篇 第三章 深入Servlet技术 1 浏览器的request http数据报中包含一些关键信息,如访问方式.所用的http版本.所用的浏览器.当前的页面地址等信息 2 http查询数据方 ...
- 记录一次成功CICD完整亲身实践从此踏进入Devops大门
Devops概念 DevOps 强调通过一系列手段来实现既快又稳的工作流程,使每个想法(比如一个新的软件功能,一个功能增强请求或者一个 bug 修复)在从开发到生产环境部署的整个流程中,都能不断地为用 ...
- 我的邮箱客户端程序Popmail
05年的时候写了一个邮箱客户端程序.当时主要目的是研究POP3和SMTP协议,同时锻炼自己的网络编程能力.当然了,如果自己写的邮箱客户端能够满足自身的日常工作需要,而不是频繁的登录不同的网页邮箱,那就 ...