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 实践 ...
随机推荐
- 【STM32】使用SDIO进行SD卡读写,包含文件管理FatFs(四)-介绍库函数,获取一些SD卡的信息
其他链接 [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(一)-初步认识SD卡 [STM32]使用SDIO进行SD卡读写,包含文件管理FatFs(二)-了解SD总线,命令的相关介绍 ...
- Tomcat中的Server.xml配置详解
Tomcat中的Server.xml配置详解 Tomcat Server的结构图如下: 该文件描述了如何启动Tomcat Server <Server> <Listener /> ...
- 节省内存的循环banner(一)
循环banner是指scrollview首尾相连,循环播放的效果,使用非常广泛.例如淘宝的广告栏等. 如果是简单的做法可以把所有要显示的图片全部放进一个数组里,创建相同个数的图片视图来显示图片.这样的 ...
- 用Myclipse开发Spring(转)
原文链接地址是:http://www.cnitblog.com/gavinkin555/articles/35973.html 1 新建一个项目 File----->New ----->P ...
- SpringAOP浅析
1.问题 问题:想要添加日志记录.性能监控.安全监测 2.最初解决方案 2.1.最初解决方案 缺点:太多重复代码,且紧耦合 2.2.抽象类进行共性设计,子类进行个性设计,此处不讲解,缺点一荣俱荣,一损 ...
- Apache Log4j 2 报高危漏洞,CODING 联手腾讯安全护卫软件安全
导语 12 月 9 日晚间,Apache Log4j 2 发现了远程代码执行漏洞,恶意使用者可以通过该漏洞在目标服务器上执行任意代码,危害极大. 腾讯安全第一时间将该漏洞收录至腾讯安全漏洞特征库中,C ...
- Jenkins获取jar包的快照号
目录 一.简介 二.脚本 一.简介 主要用于打jar包的工程,显示快照包的名字.当jar打包完成后,会在target目录中,截取快照名. 二.脚本 1.脚本return-version.sh #!/b ...
- shell脚本 Linux系统安全监测
一.简介 源码地址 日期:2018/4/12 介绍:监测当前Linux系统的安全配置,并给出建议 效果图: 二.使用 适用:centos6+ 语言:中文 注意:无 下载 wget https://ra ...
- java多线程6:ReentrantLock
下面看下JUC包下的一大并发神器ReentrantLock,是一个可重入的互斥锁,具有比synchronized更为强大的功能. ReentrantLock基本用法 先来看一下ReentrantLoc ...
- Typora软件使用教程
Typora软件的使用教程 Typora软件简介 Typora是一款轻便简洁的Markdown编辑器,支持即时渲染技术,这也是与其他Markdown编辑器最显著的区别.当然重点是免费. Typora编 ...