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 实践 ... 
随机推荐
- jquery总结和注意事项
			1.关于页面元素的引用通过jquery的$()引用元素包括通过id.class.元素名以及元素的层级关系及dom或者xpath条件等方法,且返回的对象为jquery对象(集合对象),不能直接调用dom ... 
- Spring Cloud服务离线
			服务离线,即某服务不能对外提供服务了.服务离线的原因有两种:服务下架与服务下线.这两种方案都是基于Actuator监控器实现的. 服务下架:将注册到Eureka Server中的Eureka Clie ... 
- linux查询健康状态,如何直观的判断你的Linux系统是否健康
			一提到对于查看系统运行的健康状况,可能大多数朋友考虑到的就是查看进程或者打开任务管理器,但是对于应用在真实生产环境中服务器的linux系统来说,以上两种方式都不是***效的查看方式,那么今天就给大家推 ... 
- maven打包插件详解
			maven-jar-plugin插件的使用及详解 该插件的xml配置及详解如下: <plugin> <groupId>org.apache.maven.plugins</ ... 
- numpy基础教程--浅拷贝和深拷贝
			在numpy中,使用等号(=)直接赋值返回的是一个视图,属于浅拷贝:要完整的拷贝一个numpy.ndarray类型的数据的话,只能调用copy()函数 # coding = utf-8 import ... 
- Mysql资料 存储索引
- 20个ios登陆界面
			原文:http://favbulous.com/post/1001/24-unique-ios-login-screen-showcase Eeve Evernote Food Recood Hips ... 
- Spring中基于注解方式管理bean
			操作步骤 第一步:导入相关jar包 spring IoC的基本包 Spring支持注解的Jar包 第二步:创建Spring配置文件,ApplicationContext.xml 引入约束和开启注解扫描 ... 
- HMS Core版本发布公告
			新增动作捕捉能力.通过简单拍摄即可获得人体3D骨骼关键点数据,广泛应用于虚拟形象.体育运动和医学分析等场景: 3D物体建模能力iOS版本上线. 查看详情>> 新增道路吸附能力.可根据坐标点 ... 
- CF1166A Silent Classroom 题解
			Content 现在有 \(n\) 名学生,我们需要将这些学生分到两个班上.对于两名在同一班级的学生,如果他们的名字首字母相同,他们就会聊天. 现在给定这些学生的名字,问最少有多少对学生会在一起聊天. ... 
