黑马程序员技术交流社区
标题: 【石家庄校区】Object类、常用API、Collection集合、泛型笔记 [打印本页]
作者: Yilin 时间: 2018-7-26 09:52
标题: 【石家庄校区】Object类、常用API、Collection集合、泛型笔记
本帖最后由 小石姐姐 于 2018-7-26 18:05 编辑
Object类、常用API、Collection集合、泛型笔记
2018.0725
Object类
java.lang.Object 类是Java语言中的根类,即所有类的父类。它中描述的所有方法子类都可以使用。在对象实例
化的时候,最终找的父类就是Object。
如果一个类没有特别指定父类, 那么默认则继承自Object类。
toString方法
public String toString() :返回该对象的字符串表示。
toString方法返回该对象的字符串表示,其实该字符串内容就是对象的类型+@+内存地址值。
由于toString方法返回的结果是内存地址,而在开发中,经常需要按照对象的属性得到相应的字符串表现形式,因此也需要重写它。
在IntelliJ IDEA中,可以点击Code 菜单中的Generate... ,也可以使用快捷键alt+insert ,点击toString() 选
项。选择需要包含的成员变量并确定。
小贴士: 在我们直接使用输出语句输出对象名的时候,其实通过该对象调用了其toString()方法.
equals方法
public boolean equals(Object obj) :指示其他某个对象是否与此对象“相等”。
调用成员方法equals并指定参数为另一个对象,则可以判断这两个对象是否是相同的。这里的“相同”有默认和自定
义两种方式。
默认地址比较
如果没有覆盖重写equals方法,那么Object类中默认进行== 运算符的对象地址比较,只要不是同一个对象,结果
必然为false。
对象内容比较
如果希望进行对象的内容比较,即所有或指定的部分成员变量相同就判定两个对象相同,则可以覆盖重写equals方
法。
重写equals()的作用:
不重写时, 自定义对象默认继承Object类的equals()方法, 通过 == 比较地址值
但开发时, 一般要重写equals()方法, 让对象根据属性值来判断是否相等
IDEA快捷键: Alt+Insert, 选 equals() and hashCode()
java.util.Objects类: JDK7 添加. 操作对象的工具类, 提供了空指针安全的方法
// 静态方法
static boolean equals(Object a, Object b): 比较两个对象是否相等
如果2个参数都是null, 返回true
如果其中一个为null, 返回false
如果2个参数都不为null, 则使用第1个参数对象的equals()方法来比较
// Objects类中equals()方法源码
[Java] 纯文本查看 复制代码
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
Date类
注意: 不要导错包! 有2个包中都有Date类, 一个是java.sql.Date, 另一个是java.util.Date
我们用的是 java.util.Date
java.util.Date类: 日期, 表示特定的瞬间, 精确到"毫秒"
// 构造方法
[Java] 纯文本查看 复制代码
Date(): 创建Date对象, 表示当前系统时间
Date(long date): 创建Date对象, 使用指定的毫秒值作为时间
// 常用成员方法
[AppleScript] 纯文本查看 复制代码
long getTime(): 获取Date对象中保存的时间毫秒值
void setTime(long time): 修改Date对象的时间
UNIX时间戳: 从0时区 1970-01-01 00:00:00 开始, 至今经过的毫秒值(1 秒 = 1000 毫秒)
10位 精确到秒 : 1494992791 = 2017/5/17 11:46:31
13位 精确到毫秒: 1494992791000 = 2017/5/17 11:46:31
DateFormat类及其构造方法
[AppleScript] 纯文本查看 复制代码
java.text.DateFormat抽象类: 用于格式化和解析时间. 提供了方便的方法
// 常用成员方法 (抽象类不能创建对象, 但可以有非抽象的方法供子类使用)
String format(Date date): 格式化, 从Date对象转换为String对象
Date parse(String source): 解析, 从String对象转换为Date对象
java.text.SimpleDateFormat类
// 构造方法
[Java] 纯文本查看 复制代码
SimpleDateFormat(String pattern): 用给定的模式和默认语言环境的日期格式符号创建对象
// 常用模式: 可在SimpleDateFormat类中查看
[AppleScript] 纯文本查看 复制代码
y: 年
M: 月
d: 日
H: 时 (24小时制)
m: 分
s: 秒
E: 星期
D: 年中的天
K: 小时(12小时制)
S: 毫秒
示例: "yyyy-MM-dd E HH:mm:ss.SSS"
结果: 2016-04-01 星期五 17:29:15.868
如果要匹配普通的英文字母, 则需要用单引号括起来: "'abc'"
如果要匹配单引号, 则使用2个单引号: "''"
DateFormat类之格式化format方法
[AppleScript] 纯文本查看 复制代码
String format(Date date): 格式化, 从Date对象转换为String对象
例如, SimpleDateFormat对象的模式是: "yyyy年MM月dd日 HH:mm:ss"
那么, 将Date格式化后就可以是这种样子: 2018年01月02日 03:04:05
DateFormat之解析parse方法
[AppleScript] 纯文本查看 复制代码
Date parse(String source): 解析, 从String对象转换为Date对象
例如, SimpleDateFormat对象的模式是: "yyyy-MM-dd"
要解析为Date对象的字符串必须符合模式: 2000-01-02
Calendar对象的获取方式
[AppleScript] 纯文本查看 复制代码
java.util.Calendar抽象类: 代表日历, 提供了不同国家的历法, 封装了很多时间属性
// 静态方法
static Calendar getInstance(): 根据当前系统设置获取合适的Calendar对象, 表示当前系统时间
// 获取日历对象的示例
Calendar c = Calendar.getInstance(); // 代表了当前时间
Calendar.getInstance() 会根据当前系统获取合适的子类对象, 我们获取到的是 GregorianCalendar
Calendar类的常用功能
java.util.Calendar抽象类: 代表日历, 提供了不同国家的历法, 封装了很多时间属性
// 静态成员变量
[AppleScript] 纯文本查看 复制代码
static int YEAR :年份
static int MONTH :月份. 注意月份数值是 0-11
static int DAY_OF_MONTH :日期
static int HOUR :小时(12小时制)
static int HOUR_OF_DAY :小时(24小时制)
static int MINITE :分钟
static int SECOND :秒
// 非静态成员方法
[AppleScript] 纯文本查看 复制代码
int get(int field): 获取指定日历字段的值 int year = cal.get(Calendar.YEAR)
void set(int field, int value): 修改指定日历字段为指定的值
void add(int field, int amount): 调整指定日历字段的值. 正数增加, 负数减少
Date getTime(): Calendar转Date
void setTime(Date d): Date转Calendar
// 示例
// 获取日期:
[AppleScript] 纯文本查看 复制代码
int day = calendar.get(Calendar.DAY_OF_MONTH);
// 修改年:
[AppleScript] 纯文本查看 复制代码
calendar.set(Calendar.YEAR, 2000);
// 修改月:
[AppleScript] 纯文本查看 复制代码
calendar.set(Calendar.MONTH, 0);
// 日期增加一天:
[AppleScript] 纯文本查看 复制代码
calendar.add(Calendar.DAY_OF_MONTHY, 1);
// 日期减少一天:
[AppleScript] 纯文本查看 复制代码
calendar.add(Calendar.DAY_OF_MONTHY, -1);
日期转换总结:
[AppleScript] 纯文本查看 复制代码
long (数学计算)
\ SimpleDateFormat
Date -------------------- String (用户输入和显示)
/
Calendar (获取时间的某个部分)
long和Date对象互转
利用Date
Date(long millis): long转Date
long getTime(): Date转long
String和Date对象互转
利用SimpleDateFormat
Date parse(String s): String转Date
String format(Date): Date转String
Calendar对象和Date对象互转
利用Calendar
Date getTime(): Calendar转Date
void setTime(Date d): Date转Calendar
System类之获取时间毫秒值
[Java] 纯文本查看 复制代码
java.lang.System类: 系统相关功能
// 静态方法
static long currentTimeMillis(): 返回当前系统时间的毫秒值
System类之数组复制方法
java.lang.System类: 系统相关功能
// 静态方法
static void arrayCopy(Object src, int srcPos, Object dest, int destPos, int length): 复制源数
组中指定长度个元素到一个新数组中
[Java] 纯文本查看 复制代码
* Object src: 源数组 (被复制的数组)
* int srcPos: 源数组索引 (从源数组的哪个索引开始复制)
* Object dest: 目标数组 (要复制到哪个数组)
* int destPos: 目标数组索引 (指定目标数组接收元素的索引位置)
* int length: 长度 (要复制的元素个数)
StringBuilder类
+号拼接字符串的问题:
String是不可变的, 使用加号进行字符串拼接, 会创建很多额外的对象, 浪费内存空间
实际上+加号在最终执行时, 会被翻译为:
new StringBuilder("原字符串").append("要拼接的字符串").toString();
额外创建了多余的StringBuilder对象
StringBuilder概述与构造
[AppleScript] 纯文本查看 复制代码
java.lang.StringBuilder类: 可变字符序列, 可以高效拼接字符串. 底层使用数组保存
// 构造方法
StringBuilder(): 构造一个空的StringBuilder容器
StringBuilder(String str): String转StringBuilder
StringBuilder常用方法
[AppleScript] 纯文本查看 复制代码
java.lang.StringBuilder类: 可变字符序列, 可以高效拼接字符串. 底层使用数组保存
// 常用方法
StringBuilder append(任意类型): 添加任意类型数据的字符串形式, 并返回当前对象
String toString(): 将当前StringBuilder对象转换为String对象
String和StringBuilder互转: 利用StringBuilder
StringBuilder(String str): String转StringBuilder
String toString(): StringBuilder转String
自动装箱与自动拆箱
装箱: 从基本类型转换为对应的包装类对象
拆箱: 从包装类对象转换为对应的基本类型
JDK 5开始, 装箱和拆箱都是**自动的**
// 自动装箱原理
Integer i2 = Integer.valueOf(4); //使用包装类中的valueOf方法
// 自动拆箱原理
int num = i.intValue();
包装类常用方法: 基本类型与字符串之间转换
基本类型转为String: 拼接空字符串
[Java] 纯文本查看 复制代码
"" + 34
true + ""
String转基本类型: 利用包装类的静态方法
static byte parseByte(String s): 将字符串参数转换为对应的byte基本类型
static short parseShort(String s): 将字符串参数转换为对应的short基本类型 Short
static int parseInt(String s): 将字符串参数转换为对应的int基本类型 Integer
static long parseLong(String s): 将字符串参数转换为对应的long基本类型
static float parseFloat(String s): 将字符串参数转换为对应的float基本类型
static double parseDouble(String s): 将字符串参数转换为对应的double基本类型
static boolean parseBoolean(String s): 将字符串参数转换为对应的boolean基本类型
今日API
java.lang.Object类: 根类, 所有类的父类
// 成员方法
String toString() :返回该对象的字符串表示
boolean equals(Object obj) :指示其他某个对象是否与此对象"相等"
java.util.Objects类: JDK7 添加. 操作对象的工具类, 提供了空指针安全的方法
// 静态方法
static boolean equals(Object a, Object b): 比较两个对象是否相等
如果2个参数都是null, 返回true
如果其中一个为null, 返回false
如果2个参数都不为null, 则使用第1个参数对象的equals()方法来比较
java.util.Date类: 日期, 表示特定的瞬间, 精确到"毫秒"
// 构造方法
Date(): 创建Date对象, 表示当前系统时间
Date(long date): 创建Date对象, 使用指定的毫秒值作为时间
// 常用成员方法
[Java] 纯文本查看 复制代码
long getTime(): 获取Date对象中保存的时间毫秒值
void setTime(long time): 修改Date对象的时间
java.text.DateFormat抽象类: 用于格式化和解析时间. 提供了方便的方法
// 常用成员方法 (抽象类不能创建对象, 但可以有非抽象的方法供子类使用)
[Java] 纯文本查看 复制代码
String format(Date date): 格式化, 从Date对象转换为String对象
Date parse(String source): 解析, 从String对象转换为Date对象
java.text.SimpleDateFormat类
// 构造方法
SimpleDateFormat(String pattern): 用给定的模式和默认语言环境的日期格式符号创建对象
// 常用模式: 可在SimpleDateFormat类中查看
y: 年
M: 月
d: 日
H: 时 (24小时制)
m: 分
s: 秒
E: 星期
D: 年中的天
K: 小时(12小时制)
S: 毫秒
java.util.Calendar抽象类: 代表日历, 提供了不同国家的历法, 封装了很多时间属性
// 静态方法
static Calendar getInstance(): 根据当前系统设置获取合适的Calendar对象, 表示当前系统时间
// 静态成员变量
[AppleScript] 纯文本查看 复制代码
static int YEAR :年份
static int MONTH :月份. 注意月份数值是 0-11
static int DAY_OF_MONTH :日期
static int HOUR :小时(12小时制)
static int HOUR_OF_DAY :小时(24小时制)
static int MINITE :分钟
static int SECOND :秒
// 非静态成员方法
[AppleScript] 纯文本查看 复制代码
int get(int field): 获取指定日历字段的值
void set(int field, int value): 修改指定日历字段为指定的值
void add(int field, int amount): 调整指定日历字段的值. 正数增加, 负数减少
Date getTime(): Calendar转Date
void setTime(Date d): Date转Calendar
java.lang.System类: 系统相关功能
// 静态方法
[AppleScript] 纯文本查看 复制代码
static long currentTimeMillis(): 返回当前系统时间的毫秒值
static void arrayCopy(Object src, int srcPos, Object dest, int destPos, int length): 复制源数
组中指定长度个元素到一个新数组中
* Object src: 源数组 (被复制的数组)
* int srcPos: 源数组索引 (从源数组的哪个索引开始复制)
* Object dest: 目标数组 (要复制到哪个数组)
* int destPos: 目标数组索引 (指定目标数组接收元素的索引位置)
* int length: 长度 (要复制的元素个数)
java.lang.StringBuilder类: 可变字符序列, 可以高效拼接字符串. 底层使用数组保存
// 构造方法
[AppleScript] 纯文本查看 复制代码
StringBuilder(): 构造一个空的StringBuilder容器
StringBuilder(String str): String转StringBuilder
// 常用方法
[AppleScript] 纯文本查看 复制代码
StringBuilder append(任意类型): 添加任意类型数据的字符串形式, 并返回当前对象
String toString(): 将当前StringBuilder对象转换为String对象
基本类型转为String: 拼接空字符串
"" + 34
true + ""
String转基本类型: 利用包装类的静态方法
static byte parseByte(String s): 将字符串参数转换为对应的byte基本类型
static short parseShort(String s): 将字符串参数转换为对应的short基本类型
static int parseInt(String s): 将字符串参数转换为对应的int基本类型
static long parseLong(String s): 将字符串参数转换为对应的long基本类型
static float parseFloat(String s): 将字符串参数转换为对应的float基本类型
static double parseDouble(String s): 将字符串参数转换为对应的double基本类型
static boolean parseBoolean(String s): 将字符串参数转换为对应的boolean基本类型
2018.07.26
Collection集合概述
集合: 长度可变容器, 可以存储多个对象
集合和数组的区别:
1. 数组长度不可变; 集合长度可变
2. 数组可以存基本类型或引用类型, 只能存同一种类型; 集合只能存储引用类型元素, 可以是多种类型元素
集合框架
[AppleScript] 纯文本查看 复制代码
Collection接口: 单列集合顶层
|_ List接口: 元素存取有序, 可重复, 有索引
|_ Set接口: 元素存取无序, 不可重复, 无索引
ArrayList<String> add("aaaa") add("bbb") add("ccc") add("ccc")
"aaaa" "bbb" "ccc"
HashSet<String> add("aaaa") add("bbb") add("ccc")
"bbb" "ccc" "aaaa"
Collection常用功能
java.util.Collection接口:
// 成员方法(子类都会实现)
[AppleScript] 纯文本查看 复制代码
boolean add(E e): 把给定的对象添加到当前集合中
void clear(): 清空集合中所有的元素
boolean remove(E e): 把给定的对象在当前集合中删除
boolean contains(E e): 判断当前集合中是否包含给定的对象
boolean isEmpty(): 判断当前集合是否为空(没有元素)
int size(): 返回集合中元素的个数
Object[] toArray(): 把集合中的元素,存储到数组中
Iterator<E> iterator(): 获取集合的迭代器对象 (后面讲到)
Iterator接口: 迭代器
测试Collection接口的方式:
使用多态方式创建对象: Collection c = new ArrayList();
编译看左边, 这样只能调用Collection接口中定义的方法, 不会出现子类特有方法
迭代器
迭代: 类似于遍历, 判断是否有下一个元素, 有则取出下一个, 直到没有
迭代器: 用于遍历集合的对象
java.util.Collection<E>接口:
// 成员方法(子类都会实现)
[AppleScript] 纯文本查看 复制代码
Iterator<E> iterator(): 获取集合的迭代器对象
java.util.Iterator<E>接口: 迭代器
// 成员方法
[AppleScript] 纯文本查看 复制代码
boolean hasNext(): 判断是否有下一个元素
E next(): 获取下一个元素
void remove(): 删除next指向的元素
使用迭代器遍历集合的3步:
1. 使用集合对象的 iterator() 获取迭代器对象, 用 Iterator 接口接收.(多态)
2. 使用 Iterator 接口中的 hasNext() 方法, 判断是否有下一个元素
3. 使用 Iterator 接口中的 next() 方法, 获取下一个元素
使用迭代器的代码实现
// 使用迭代器遍历集合的标准写法:
Iterator<元素类型> iterator = 集合对象.iterator();
while (iterator.hasNext()) {
元素类型 变量名 = iterator.next();
}
迭代器的实现原理
集合和迭代器对象的关系:
每个集合都有对应的一个迭代器对象
迭代器的原理:
迭代器有一个指针(其实就是个变量保存索引值), 最初指向集合的 -1 索引
hasNext() 方法可以判断下一个索引是否有元素
next() 方法移动指针到下一个索引, 并返回元素
注意事项:
1. 迭代器对象迭代完毕后, 指针已经指向最后一个元素, 没有下一个元素了. 如果想再次从头遍历集合, 要获取
新的迭代器对象
2. 在使用迭代器迭代的过程中, 如果执行了改变集合长度的操作 (如add(), remove(), clear()), 则会抛出
ConcurrentModificationException 并发修改异常. 如果要在迭代的过程中添加, 删除元素, 要使用迭代器自带的方
法, 而不能使用集合的方法
增强for循环
增强for: 也称foreach循环, JDK 5出现, 用于遍历集合, 底层采用迭代器
作用:
遍历数组
遍历集合
增强for格式:
for(元素的数据类型 变量名 : Collection集合或数组名){
//操作代码
}
// 数组示例
[AppleScript] 纯文本查看 复制代码
int[] arr = {1,2,3};
for (int i : arr) {
System.out.println(i);
}
// 集合示例
[AppleScript] 纯文本查看 复制代码
Collection<Integer> c = new ArrayList<>();
for (int i : c) {
System.out.println(i);
}
增强for对于数组和集合的操作:
对数组只是写法上的优化, 底层还是普通for循环
对集合是通过迭代器实现的
增强for快捷键:对象名.for
增强for, 普通for, 迭代器的区别:
增强for:
优点: 获取元素很方便, 格式简单
缺点: 没有普通for中的索引, 没有迭代器对象可以进行元素的增删
应用场景: 适用于遍历获取数组和集合元素的场景
普通for:
优点: 有索引可以使用, 某些方式可以在遍历过程中增删元素
缺点: 格式繁琐
应用场景: 需要用到索引的场景
迭代器:
优点: 可以使用迭代器对象的方法操作元素
缺点: 格式繁琐
应用场景: 需要在迭代过程中增删元素的场景
泛型
泛型: Generic. JDK 5 增加. 是一种未知的数据类型
定义集合时, 某些方法不知道使用什么类型时, 就可以使用泛型
创建集合对象时, 需要确定泛型具体的类型
泛型可以看作是一个变量, 用来接收数据类型
泛型的好处
不使用泛型的问题:
集合实际存储的是 Object 类型, 存入的元素无论是什么类型, 都会被提升为 Object, 取出来的也是 Object,
要想调用元素特有方法, 就要向下转型, 有可能发生类型转换异常 ClassCastException
泛型的好处:
1. 避免了类型转换的麻烦
2. 将运行时的类型转换异常, 转移到了编译时期 (有利于程序员提前发现问题)
定义和使用含泛型的类
定义泛型
<泛型名>
泛型的定义和使用
泛型在定义时, 不能是具体的类型, 只是一个变量名
泛型在使用时, 必须是具体的数据类型
// 带有泛型的类定义格式
修饰符 class 类名<代表泛型的名字> { // 泛型的变量一般用一个大写字母表示, 但也可以是多个字母
}
类中泛型在创建对象时, 确定泛型的具体类型
代码:
/*
定义类: GenericClass, 带有泛型 E
私有成员变量: E name;
提供 set/get方法
*/
[AppleScript] 纯文本查看 复制代码
public class GenericClass<E> { // 类上声明了泛型, 类中的所有方法和成员变量都可以使用该泛型
private E name; // 成员变量的类型用泛型
public E getName() { // 成员方法的返回值类型用泛型
return name;
}
public void setName(E name) { // 成员方法的参数类型用泛型
this.name = name;
}
}
/*
需求:
定义类: GenericClass, 带有泛型 E
私有成员变量: E name;
提供 set/get方法
定义测试类
创建GenericClass对象, 将泛型替换为Integer, 调用setName()设置值并调用getName()获取值并打印
创建GenericClass对象, 将泛型替换为String, 调用setName()设置值并调用getName()获取值并打印
*/
[AppleScript] 纯文本查看 复制代码
public class Test {
public static void main(String[] args) {
// 创建对象, 泛型为Integer
GenericClass<Integer> gc1 = new GenericClass<>();
gc1.setName(1);
Integer name1 = gc1.getName();
System.out.println(name1);
// 创建对象, 泛型为String
GenericClass<String> gc2 = new GenericClass<>();
gc2.setName("这是字符串");
String name2 = gc2.getName();
System.out.println(name2);
}
}
定义含有泛型的方法与使用
方法中的泛型定义位置:
修饰符 和 返回值类型 之间
// 带有泛型的方法定义格式
修饰符 <代表泛型的名字> 返回值类型 方法名(参数){
}
方法中定义泛型后, 返回值类型和参数类型都可以使用泛型
方法泛型的使用:
在调用方法时确定泛型的具体类型
代码演示:
需求:
定义类: GenericMethod
定义成员方法:
[AppleScript] 纯文本查看 复制代码
public <M> void method(M m) {
System.out.println(m);
}
定义静态方法:
[AppleScript] 纯文本查看 复制代码
public static <S> void staticMethod(S s) {
System.out.println(s);
}
定义测试类:
创建GenericMethod对象
调用method()方法, 传递10
调用method()方法, 传递"abc"
调用staticMethod()方法, 传递"静态方法"
代码:
[AppleScript] 纯文本查看 复制代码
public class GenericMethod {
public <M> void method(M m) { // 方法上声明的泛型, 只能在方法内部使用
// M m2 = null; // 局部变量也可以
System.out.println(m);
}
public static <S> void staticMethod(S s) {
System.out.println(s);
}
// 方法返回值也可以使用方法声明的泛型
[AppleScript] 纯文本查看 复制代码
public <P> P getP(P p) {
return p;
}
}
public class Test {
public static void main(String[] args) {
// 创建GenericMethod对象
GenericMethod gm = new GenericMethod();
// 调用方法时, 根据参数类型确定具体的类型
gm.method(10);
gm.method("abc");
GenericMethod.staticMethod("静态方法");
String result = gm.getP("abc");
System.out.println(result);
}
}
定义与使用含有泛型的接口
定义泛型接口与定义泛型类一样
// 带有泛型的类定义格式
修饰符 interface接口名<代表泛型的变量> {
}
实现类实现了泛型接口后可以有2种选择:
1. 定义实现类时就确定泛型的具体类型
2. 定义实现类时仍然沿用泛型, 直到创建该类对象时才确定泛型的具体类型
代码演示:
/*
定义含有泛型的接口
*/
[AppleScript] 纯文本查看 复制代码
public interface GenericInterface<I> {
public abstract void method(I i);
}
/*
含有泛型的接口,第一种使用方式:定义接口的实现类,实现接口,指定接口的泛型
[AppleScript] 纯文本查看 复制代码
public interface Iterator<E> {
E next();
}
Scanner类实现了Iterator接口,并指定接口的泛型为String,所以重写的next方法泛型默认就是String
[AppleScript] 纯文本查看 复制代码
public final class Scanner implements Iterator<String>{
public String next() {}
}
*/
[AppleScript] 纯文本查看 复制代码
public class GenericInterfaceImpl1 implements GenericInterface<String>{
@Override
public void method(String s) {
System.out.println(s);
}
}
/*
含有泛型的接口第二种使用方式:接口使用什么泛型,实现类就使用什么泛型,类跟着接口走
就相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型
[AppleScript] 纯文本查看 复制代码
public interface List<E>{
boolean add(E e);
E get(int index);
}
public class ArrayList<E> implements List<E>{
public boolean add(E e) {}
public E get(int index) {}
}
*/
public class GenericInterfaceImpl2<I> implements GenericInterface<I> {
@Override
public void method(I i) {
System.out.println(i);
}
}
/*
测试含有泛型的接口
*/
[AppleScript] 纯文本查看 复制代码
public class Demo04GenericInterface {
public static void main(String[] args) {
//创建GenericInterfaceImpl1对象
GenericInterfaceImpl1 gi1 = new GenericInterfaceImpl1();
gi1.method("字符串");
//创建GenericInterfaceImpl2对象
GenericInterfaceImpl2<Integer> gi2 = new GenericInterfaceImpl2<>();
gi2.method(10);
GenericInterfaceImpl2<Double> gi3 = new GenericInterfaceImpl2<>();
gi3.method(8.8);
}
}
泛型定义总结:
定义在类上的泛型:
有效范围: 整个类中都有效
何时确定具体类型: 创建该类对象时确定泛型的具体类型
定义在方法上的泛型:
有效范围: 方法中(包括返回值类型和参数类型)有效
何时确定具体类型: 调用方法传参时确定泛型的具体类型
定义在接口上的泛型:
有效范围: 接口中
何时确定具体类型:
1. 子接口或实现类定义时确定泛型的具体类型
2. 创建实现类对象时确定泛型的具体类型
泛型通配符
泛型通配符:
不知道使用什么类型来接收时, 此时可以使用 <?> 来表示未知通配符
[Java] 纯文本查看 复制代码
示例: List<?> list 接收泛型是任意类型的List对象
注意: 只能接收数据, 不能调用方法存储元素
List<?> list 这种集合不能调用 add() 添加元素, 只能调用 get() 获取元素
List<?> list 其实是一个变量, 所以可以将一个集合赋值给它
如: List<?> list = new ArrayList<String>();
使用方式:
不能创建对象使用
只能作为方法参数使用. (减少方法重载)
泛型的上限:
[Java] 纯文本查看 复制代码
格式: 类型名称<? extends 类名> 对象名称
示例: List<? extends Number> list
作用: 只能接收该类型及其子类 (Number及其子类的泛型)
泛型的下限:
[AppleScript] 纯文本查看 复制代码
格式: 类型名称<? super 类名> 对象名称
示例: List<? super Number> list
作用: 只能接收该类型及其父类型 (Number及其父类的泛型)
泛型通配符练习
需求:
定义Person类, 不用定义成员
定义Student类, 继承Person类, 不用定义成员
定义测试类
在测试类中, 定义方法:
[Java] 纯文本查看 复制代码
public static void printExtends(Collection<? extends Person> list) {
// 使用增强for遍历集合中的元素打印出来
}
public static void printSuper(Collection<? super Person> list) {
// 使用迭代器遍历集合元素打印出来
}
创建ArrayList<Person>集合, 添加3个Person对象
创建ArrayList<Student>集合, 添加3个Student对象
分别调用2个方法测试能够传入的集合有哪些
[AppleScript] 纯文本查看 复制代码
public class Person {
}
public class Student extends Person {
}
/*
需求:
定义Person类, 不用定义成员
定义Student类, 继承Person类, 不用定义成员
定义测试类
在测试类中, 定义方法:
public static void printExtends(Collection<? extends Person> list) {
// 使用增强for遍历集合中的元素打印出来
}
public static void printSuper(Collection<? super Person> list) {
// 使用迭代器遍历集合元素打印出来
}
创建ArrayList<Person>集合, 添加3个Person对象
创建ArrayList<Student>集合, 添加3个Student对象
分别调用2个方法测试能够传入的集合有哪些
*/
[AppleScript] 纯文本查看 复制代码
public class Test {
public static void main(String[] args) {
// 创建泛型为Person的集合
ArrayList<Person> personList = new ArrayList<>();
personList.add(new Person());
personList.add(new Person());
personList.add(new Person());
// 创建泛型为Student的集合
ArrayList<Student> studentList = new ArrayList<>();
studentList.add(new Student());
studentList.add(new Student());
studentList.add(new Student());
// Collection<? extends Person>
printExtends(personList); // 可以接收泛型为Person类型的集合
printExtends(studentList); // 可以接收泛型为Student类型的集合
// Collection<? super Person>
printSuper(personList); // 可以接收泛型为Person类型的集合
printSuper(studentList); // Student不是Person的父类, 不能接收
}
public static void printExtends(Collection<? extends Person> list) {
// 使用增强for遍历集合中的元素打印出来
for (Person person : list) {
System.out.println(person);
}
}
public static void printSuper(Collection<? super Person> list) {
// 使用迭代器遍历集合元素打印出来
Iterator<? super Person> iterator = list.iterator();
while (iterator.hasNext()) {
Object o = iterator.next();
System.out.println(o);
}
}
}
| 欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |