1.泛型概述和基本使用
泛型:
JDK1.5之后引入的一种机制。是一种把类型明确的工作,推迟到创建对象或者调用方法的时候,才去明确的特殊的类型。参数化类型,把类型当作参数一样的传递。
泛型的格式:
<数据类型> 这里的数据类型只能是引用数据类型
泛型好处:
(1): 把运行时期的问题提前到了编译期间;
(2): 避免了强制类型转换、向下转型;
(3): 优化了程序设计,解决了黄色警告线,提高代码的扩展性。
注意:泛型只在编译期有效 但在运行期就擦除了。
泛型基本使用:
public static void main(String[] args) {
ArrayList<String> list2 = new ArrayList<String>();
list2.add("abc");
// list2.add(100);报错
String s = list2.get(0);
System.out.println(s);
}
ArrayList存储自定义对象并遍历泛型版:
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("张国荣",23));
list.add(new Student("张国荣", 23));
list.add(new Student("张家辉", 23));
list.add(new Student("张震岳", 23));
list.add(new Student("张子豪", 23));
/*
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Student student = (Student) iterator.next();
System.out.println(student);
}*/
Iterator<Student> iterator = list.iterator();
while (iterator.hasNext()) {
Student student = iterator.next();
System.out.println(student);
}
}
泛型的由来:
通过Object转型问题引入,早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。也就存在这隐患,所以Java提供了泛型来解决这个安全问题。
泛型类的使用:
把泛型定义在类上
定义格式: public class 类名<泛型类型1,…>
注意事项: 泛型类型必须是引用类型
public class MyClass<T> {
private T t;
private Integer num;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
泛型方法的使用:
把泛型定义在方法上
定义格式: public <泛型类型> 返回类型 方法名(泛型类型 变量名)
案例演示: 泛型方法的使用
public static void main(String[] args) {
MyObjct<String, Integer> stringIntegerMyObjct = new MyObjct<>();
stringIntegerMyObjct.setU(100);
stringIntegerMyObjct.setR("abc");
String r = stringIntegerMyObjct.getR();
Integer u = stringIntegerMyObjct.getU();
}
public class MyObjct<R,U> {
private R r;
private U u;
public R getR() {
return r;
}
public void setR(R r) {
this.r = r;
}
public U getU() {
return u;
}
public void setU(U u) {
this.u = u;
}
}
泛型接口使用:
把泛型定义在接口上
定义格式: public interface 接口名<泛型类型>
案例演示: 泛型接口的使用
public interface MyInterface<A> {
public abstract void test(A a);
}
//子类实现接口时,可以明确接口上的泛型具体是什么类型
public class MyA implements MyInterface<Integer>{
@Override
public void test(Integer integer) {
System.out.println("abc");
}
}
public static void main(String[] args) {
//采用匿名 内部类的这种方式,在创建接口的子类对象时,可以明确接口上的泛型具体是什么类型。
new MyInterface<String>(){
@Override
public void test(String s) {
}
};
MyB<Double> doubleMyB = new MyB<>();
}
泛型高级之通配符
<?>: 任意类型,如果没有明确,那么就是Object以及任意的Java类了,? 表示任意的数据类型? extends E: 向下限定,E及其子类, ? 表示的是E或者E的子类
? super E: 向上限定,E及其父类, ? 表示的是E或者E的父类
泛型如果明确了数据类型以后,那么要求左右两边的数据类型必须一致
public class MyTest {
public static void main(String[] args) {
//? 泛型通配符
ArrayList<?> objects = new ArrayList<Dog>();
ArrayList<?> objects2 = new ArrayList<Cat>();
ArrayList<?> objects3 = new ArrayList<Animal>();
System.out.println("====================================");
//向上限定
ArrayList<? super Cat> list = new ArrayList<Animal>();
ArrayList<? super Animal> list2 = new ArrayList<Animal>();
ArrayList<? super Animal> list3 = new ArrayList<Object>();
//向下限定
ArrayList<? extends Animal> list4 = new ArrayList<Animal>();
ArrayList<? extends Animal> list5 = new ArrayList<Cat>();
ArrayList<? extends Animal> list6 = new ArrayList<Dog>();
System.out.println("============================================");
ArrayList<Integer> a= new ArrayList<>();
a.add(200);
ArrayList<Integer> b = new ArrayList<>();
b.add(2000);
a.addAll(b);
}
}
class Animal{
}
class Dog extends Animal{
}
class Cat extends Animal{
}
2.增强for的概述和使用
简化数组和Collection集合的遍历
格式:
for(元素数据类型 变量 : 数组或者Collection集合) {
使用变量即可,该变量就是元素
}
注意事项:
增强for的目标要判断是否为null;
注意新式for循环,你在迭代集合的途中,不能增删元素,会报并发修改异常
public static void main(String[] args) {
// 新式 for循环 JDK1.5 引入的语法
int[] arr={20,30,50};
// for(容器中的元素的数据类型 变量名:容器名)
for(int a:arr){
System.out.println(a);
}
System.out.println("==============================");
ArrayList<Integer> integers = new ArrayList<>();
integers.add(200);
integers.add(200);
integers.add(200);
integers.add(200);
for(Integer num:integers){
System.out.println(num);
}
System.out.println("===============================");
for (int i : arr) {
}
for (Integer integer : integers) {
}
}
ArrayList存储字符串并遍历增强for版
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
integers.add(200);
integers.add(200);
integers.add(200);
integers.add(200);
//ConcurrentModificationException 并发修改异常
//新式for循环在遍历集合时,底层用的还是迭代器,你在遍历途中,如果改变集合的长度,就会报并发修改异常。
for (Integer integer : integers) {
if(integer.intValue()==200){
integers.add(300);
}
}
System.out.println(integers);
}
3.可变参数的概述和使用
定义方法的时候不知道该定义多少个参数
格式:
修饰符 返回值类型 方法名(数据类型… 变量名){}
注意事项:
a: 这里的变量其实是一个数组
b: 如果一个方法有可变参数,并且有多个参数,那么可变参数肯定是最后一个
public static void main(String[] args) {
int sum = add(1, 2);
int sum2 = add(1, 2, 3);
int sum3 = add(1, 2, 3, 4);
System.out.println(sum);// 3
System.out.println(sum2);// 6
System.out.println(sum3);// 9
}
//可变参数,一次可以接收多个同类型的参数
//可变参数 本质是是个数组
//如果一个方法的形参有多个参数,那么可变参数,应该是最后一个。
private static int add(int b,int... a) {
//System.out.println(a.length);
int sum=b;
for (int i : a) {
sum += i;
}
return sum;
}
4.Arrays工具类的asList()方法的使用
将数组转换成集合
注意事项:
得到的集合长度是不可变的,你不能往这个转换后的集合中 添加元素(add) 和 删除元素(remove),只能获取元素(get)。
public static void main(String[] args) {
//把一个数组转换集合。
int[] arr={20,30,40};
//我传的是一个基本类型的数组,他是把这个数组对象,放到集合中
List<int[]> ints = Arrays.asList(arr);
System.out.println(ints);
System.out.println(ints.get(0)[0]);
Integer[] arr2 = {20, 30, 40};
//我传入的是一个包装类型的数组,他是把数组中的元素,取出来放到集合中
List<Integer> integers = Arrays.asList(arr2);
System.out.println(integers);
Integer[] arr3 = {20, 30, 40};
Integer[] arr4 = {20, 30, 400};
//如果你传入多个包装类型的数组,那么他是把多个数组对象,放到集合中。
List<Integer[]> integers1 = Arrays.asList(arr3, arr4);
Integer integer = integers1.get(1)[2];
System.out.println(integer);
//也可以这样得到一个集合。
List<Integer> integers2 = Arrays.asList(20, 20, 30, 50, 30);
System.out.println(list.get(0));
//list.add(300);
//UnsupportedOperationException
//list.remove(0);
//注意:通过Arrays.asList() 这种方式的得到集合,不能再次改变集合的长度,也就是说,你不能增删元素。
}
集合嵌套之ArrayList嵌套ArrayList
A:需求:
我们班有学生,每一个学生是不是一个对象。所以我们可以使用一个集合表示我们班级的学生ArrayList< Student >
但是我们旁边还有班级,每个班级也是一个ArrayList< Student >。
而我现在有多个ArrayList< Student >。也要用集合存储,怎么办呢?
------集合嵌套之ArrayList嵌套ArrayList
// 定义大的集合
ArrayList<ArrayList> allClassList = new ArrayList<ArrayList>() ;
// 创建每一个班的集合
ArrayList jcClassList = new ArrayList() ;
public class MyTest {
public static void main(String[] args) {
Student C = new Student("C罗", 28);
Student B1 = new Student("贝尔", 24);
Student B2 = new Student("本泽马", 26);
Student M = new Student("梅西", 26);
Student S = new Student("苏亚雷斯", 26);
Student N = new Student("内马尔", 22);
ArrayList<ArrayList<Student>> students = new ArrayList<>();
ArrayList<Student> HM = new ArrayList<>();
ArrayList<Student> BS = new ArrayList<>();
HM.add(C);
HM.add(B1);
HM.add(B2);
BS.add(M);
BS.add(S);
BS.add(N);
students.add(HM);
students.add(BS);
for (ArrayList<Student> student : students) {
for (Student student1 : student) {
System.out.println(student1.getName() + "===" + student1.getAge());
}
System.out.println();
}
}
}