目录
🥅初识泛型机制
⭐️JDK5.0之后推出的新特性:泛型
⭐️泛型这种语法机制,只在程序编译阶段起作用,只是给编译器参考的(运行阶段泛型没用)
⭐️使用了泛型优点是什么?
第一:集合中存储的元素类型统一了。
第二:从集合中取出的元素类型是泛型指定的类型,不需要进行大量的“向下转型”!⭐️泛型的缺点是什么?
导致集合中存储的元素缺乏多样性!
❤️例1:泛型的用法
对于泛型就相当于范围缩小了,对于一个集合我们可以加进去任何类型的元素;当我们调用迭代器的next()方法时,取出来的类型实际上是Object类型;我们去调用类中的方法就需要向下转型;但是如果我们指定一个泛型的范围,就不需要向下转型,存取其它范围的类型就会报错!我们来通过一个例题感受一下吧!
package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class GenericTest01 {
public static void main(String[] args) {
//1.不使用泛型
List mylist = new ArrayList();
//1.1.创建对象
Cat c = new Cat();
Bird b = new Bird();
//1.2.增加对象到集合当中
mylist.add(c);
mylist.add(b);
//1.3.获取迭代器,遍历集合调用move方法
Iterator it = mylist.iterator();
while(it.hasNext()){
// 取出来的对象默认是Object类型;Object里面没有move()方法
Object obj = it.next();
// 向下转型
if(obj instanceof Animal){
Animal animal = (Animal)obj;
animal.move();
}
}
//2.使用泛型
// 使用泛型List<Animal>之后,表示List集合中只允许存储Animal类型的数据。
// 用泛型来指定集合中存储的数据类型。
List<Animal> mylist = new ArrayList<Animal>();
//2.1.创建对象
Cat c = new Cat();
Bird b = new Bird();
//2.2.增加元素
mylist.add(c);
mylist.add(b);
//2.3.获取迭代器,遍历调用move方法
// 这个表示迭代器迭代的是Animal类型。
Iterator<Animal> it = mylist.iterator();
while(it.hasNext()){
// 使用泛型<Animal>,取出来的元素是Animal类型
Animal animal = it.next();
// 不需要向下转型,直接调用
animal.move();
// 但是调用子类中特有的方法还是需要向下转型,只是方便了一个环节
if(animal instanceof Cat){
Cat cat = (Cat)animal;
cat.catchMouse();
}
if(animal instanceof Bird){
Bird bird = (Bird)animal;
bird.fly();
}
}
}
}
class Animal {
// 父类自带方法
public void move(){
System.out.println("动物在移动!");
}
}
class Cat extends Animal {
// 特有方法
public void catchMouse(){
System.out.println("猫抓老鼠!");
}
}
class Bird extends Animal {
// 特有方法
public void fly(){
System.out.println("鸟儿在飞翔!");
}
}
❤️例2:自动类型推断
JDK8之后引入了:自动类型推断机制。(又称为钻石表达式)
package com.bjpowernode.javase.collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class GenericTest02 {
public static void main(String[] args) {
// ArrayList<这里的类型会自动推断>(),前提是JDK8之后才允许。
List<Animal> myList = new ArrayList<>(); //自动类型推断
//添加对象到集合
myList.add(new Animal());
myList.add(new Cat());
myList.add(new Bird());
//遍历
Iterator<Animal> iterator = myList.iterator();
while(iterator.hasNext()){
Animal an = iterator.next();
an.move();
}
// 在比如:只存String类型的集合
List<String> str = new ArrayList<>(); //自动类型推断
str.add("http://www.126.com");
str.add("http://www.baidu.com");
str.add("http://www.bjpowernode.com");
//str.add(new String(123)); //错误,类型不匹配
System.out.println(str.size()); //3
// 遍历
Iterator<String> it2 = str.iterator();
while(it2.hasNext()){
// 如果没有使用泛型,还需要判断是不是一个String
Object obj = it2.next();
if(obj instanceof String){
String ss = (String)obj;
ss.substring(7);
}
// 使用泛型表达式,直接通过迭代器获取了String类型的数据
String s = it2.next();
// 直接调用String类的substring方法截取字符串。
String newString = s.substring(7);
System.out.println(newString);
}
}
}
🥅自定义泛型
⭐️有了上面对泛型的理解,我们能让自己定义的类也具有泛型这种特性吗?下面让我们一起来自定义泛型!
⭐️自定义泛型的时候,<> 尖括号中的是一个标识符,随便写。
⭐️java源代码中经常出现的是:<E>和<T> 都是出现在类上定义
①E是Element单词首字母;使用E一般出现在方法的参数列表里。
②T是Type单词首字母;一般出现在方法的返回值类型上。
package com.bjpowernode.javase.collection;
//自定义泛型
public class GenericTest03<E> { //E只是标识符,随便写,一般写E或者T
//提供一个方法,注意里面参数
public void doSome(E e){
System.out.println(e);
}
//程序入口
public static void main(String[] args) {
//1、创建对象,假如这个方法只能调用用String类型
GenericTest03<String> gt = new GenericTest03<>(); //自动类型推断
//gt.doSome(10); //类型不匹配
gt.doSome("abc"); //这个方法传参只能跟String类型
// 创建对象,假如这个方法只能调用用Integer类型
GenericTest03<Integer> gt2 = new GenericTest03<>();
//gt2.doSome("abc"); //类型不匹配
gt2.doSome(100); //自动装箱
//2、定义一个方法,返回的类型要与类的泛型类型保持一致
MyIterator<String> mt = new MyIterator<>();
String str = mt.get(); //返回类型只能是String
MyIterator<Animal> mt2 = new MyIterator<>();
Animal an = mt2.get(); //返回类型只能是Animal
//3、定义了泛型我们不用,参数就是Object类型
GenericTest03 gt3 = new GenericTest03();
gt3.doSome(new Object()); //参数就是Object类型
}
}
class MyIterator<T>{
public T get(){
return null;
}
}
🥅增强for循环(foreach)
⭐️JDK5.0之后推出了一个新特性:叫做增强for循环,或者叫做foreach
⭐️我们已经学习了for循环,那么什么又是增强for循环呢?我们先看语法:
for(元素类型 变量名 : 数组或集合){
System.out.println(变量名);
}
⭐️增强for循环的缺点:没有下标!
package com.bjpowernode.javase.collection;
public class ForEachTest01 {
public static void main(String[] args) {
// 1.定义一个数组
int[] arr = {22,3,9,5,6,8};
// 2.遍历打印(普通for循环)
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
// 3.增强for循环
for(int i:arr){
// foreach有一个缺点:没有下标。在需要使用下标的循环中,不建议使用增强for循环。
// i就是数组中的元素(数组中的每一个元素)
System.out.println(i);
}
}
}
❤️例:集合使用foreach
对于有下标的集合,我们现在就学到了三种打印方式:迭代器、利用下标、foreach
package com.bjpowernode.javase.collection;
import java.util.*;
//集合使用foreach
public class ForEachTest02 {
public static void main(String[] args) {
// 创建List集合
List<String> strList = new ArrayList<>();
// 增加元素
strList.add("hello");
strList.add("world");
strList.add("kitty");
//1. 遍历,使用迭代器
Iterator<String> it = strList.iterator();
while(it.hasNext()){
System.out.print(it.next()+" ");
}
System.out.println();
//2. 使用下标方式
for (int i = 0; i < strList.size(); i++) {
System.out.print(strList.get(i)+" ");
}
System.out.println();
//3. 使用foreach
// 因为泛型使用的是String类型,所以是:String s
for (String s:strList) {
System.out.print(s+" ");
}
}
}
本文含有隐藏内容,请 开通VIP 后查看