常用小结

发布时间 2023-07-08 08:48:48作者: 太阳终将升起

 

Java基础

泛型

泛型的概念

编译时检查非法的类型数据结构,本质就是参数化类型,也就是所操作的数据类型被指定为类型数据结构.

泛型类

 

定义语法

class 类名称<泛型标识,泛型标识,...>{

private 泛型标识 变量名;

......

}

常用泛型标识:T E K V

 

泛型类注意事项

泛型类,如果没有指定具体的数据类型,此时,操作类型是Ob;ject

泛型的类型参数只能是类类型,不能是基本数据类型

泛型类型在逻辑上可以看成是多个不同的类型,但实际上都是相同类型

eg1

public class Generic<T> {

private T key;

 

public Generic(T key) {

this.key = key;

}

 

public T getKey() {

return key;

}

 

public void setKey(T key) {

this.key = key;

}

 

@Override

public String toString() {

return "Generic{" +

"key=" + key +

'}';

}

}

 

public class MainClass {

public static void main(String[] args) {

Generic<String> strGeneric=new Generic<>("a");

String key1 = strGeneric.getKey();

System.out.println(key1);

 

Generic<Integer> integerGeneric=new Generic<>(123);

Integer key2 = integerGeneric.getKey();

System.out.println(key2);

 

//不指定泛型,默认为Object类型,int 不是继承自Object所以不能作为限定类型

Generic generic=new Generic("ABC");

Object key3 = generic.getKey();

System.out.println(key3);

 

//泛型不支持基本数据类型

//Generic<int> generic1=new Generic<int>(100);

 

//同一泛型类,根据不同的数据类型创建的对象,本质上是同一类型

System.out.println(strGeneric.getClass());

System.out.println(integerGeneric.getClass());

System.out.println(strGeneric.getClass()==integerGeneric.getClass());

}

}

eg2:模拟抽奖器

/**

* 抽奖器

* @param <T>

*/

public class ProductGetter<T> {

Random random=new Random();

 

//奖品

private T product;

 

//奖品池

ArrayList<T> list=new ArrayList<>();

 

//添加奖品

public void addProduct(T t){

list.add(t);

}

 

//抽奖

public T getProduct(){

product=list.get(random.nextInt(list.size()));

return product;

}

}

 

public class MainClass {

public static void main(String[] args) {

//创建抽奖器对象,指定数据类型

ProductGetter<String> stringProductGetter=new ProductGetter<>();

String[] strProduct={"苹果手机","华为手机","扫他机器人","咖啡机"};

//给抽奖器中填充奖品

for (int i=0;i<strProduct.length;i++){

stringProductGetter.addProduct(strProduct[i]);

}

String product = stringProductGetter.getProduct();

System.out.println("恭喜您抽中了:"+product);

}

}

泛型类派生子类

子类也是泛型类,子类和父类的泛型类型要一致

class ChildGeneric<T> extends Generic<T>

子类不是泛型类,父类要明确泛型的数据类型

class ChildGeneric extends Generic<String>

eg:

public class Parent<E> {

private E value;

 

public E getValue() {

return value;

}

 

public void setValue(E value) {

this.value = value;

}

}

 

public class ChildFirst<T,E,K> extends Parent<T>{

@Override

public T getValue() {

return super.getValue();

}

}

 

public class ChildSecond extends Parent<Integer>{

@Override

public Integer getValue() {

return super.getValue();

}

 

@Override

public void setValue(Integer value) {

super.setValue(value);

}

}

 

public class MainClass {

public static void main(String[] args) {

ChildFirst<String> childFirst=new ChildFirst<>();

childFirst.setValue("abc");

String value = childFirst.getValue();

System.out.println(value);

ChildSecond childSecond=new ChildSecond();

childSecond.setValue(100);

Integer value1 = childSecond.getValue();

System.out.println(value);

}

}

泛型接口

 

定义

interface 接口名称<泛型标识,泛型标识,...>{

泛型标识 方法名();

......

}

泛型接口的使用

实现类不是泛型类,接口要明确实现接口的数据类型

实现类也是泛型类,实现类要包含泛型接口的泛型标识,可以扩展

public interface Generator<T> {

T getKey();

}

//对应a

public class Apple implements Generator<String>{

@Override

public String getKey() {

return "hello generic";

}

}

//对应b

public class Pair<T,E> implements Generator<T>{

private T key;

private E value;

 

public Pair(T key, E value) {

this.key = key;

this.value = value;

}

 

@Override

public T getKey() {

return key;

}

 

public E getValue() {

return value;

}

}

 

public class Test05 {

public static void main(String[] args) {

Apple apple=new Apple();

String key = apple.getKey();

System.out.println(key);

 

Pair<String,Integer> pair=new Pair<>("count",100);

String key1 = pair.getKey();

Integer value = pair.getValue();

System.out.println(key1+":"+value);

}

}

泛型方法

泛型类,是在实例化类的时候指明泛型的具体类型

泛型方法,是在调用方法的时候指明泛型的具体类型

语法

修饰符<T,E,..>返回值类型 方法名(形参列表)

方法体...

public与返回值中间<T>非常重要,可以理解为声明此方法为泛型方法只有声明了<T>的方法才是泛型方法,

泛型类中的使用了泛型的成员方法并不是泛型方法。

<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。

与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。

 

泛型方法可变参数

public <E> void print(.. e){

for (E el :e){

System.out.println(e);

}

}

 

/**

* 抽奖器

* @param <T>

*/

public class ProductGetter<T> {

Random random=new Random();

 

//奖品

private T product;

 

//奖品池

ArrayList<T> list=new ArrayList<>();

 

//添加奖品

public void addProduct(T t){

list.add(t);

}

 

//抽奖

public T getProduct(){

product=list.get(random.nextInt(list.size()));

return product;

}

 

/**

* 定义泛型方法

* @param list 参数

* @param <E>泛型标识,具体类型,由调用方法的时候指定

* @return

*/

public <E> E getProduct(ArrayList<E> list){

return list.get(random.nextInt(list.size()));

}

 

/**

* 静态的泛型方法,采用多个泛型类型

* @param t

* @param e

* @param k

* @param <T>

* @param <E>

* @param <K>

*/

public static <T,E,K> void printType(T t, E e, K k){

System.out.println(t + "\t" + t.getClass().getSimpleName());

System.out.println(e +"\t" +e.getClass().getSimpleName());

System.out.println(k + "\t" + k.getClass().getSimpleName ());

}

 

/**

* 泛型可变参数的定义

* @param e

* @param <E>

*/

public static <E> void print(E... e){

for (int i = 0; i < e.length; i++) {

System.out.println(e[i]);

}

}

}

泛型方法总结

泛型方法能使方法独立于类而产生变化

如果 static 方法要使用泛型能力,就必须使其成为泛型方法

类型通配符

类型通配符一般是使用"?"代替具体的类型实参

所以,类型通配符是类型实参,而不是类型形参

public class Box<E> {

private E first;

 

public E getFirst() {

return first;

}

 

public void setFirst(E first) {

this.first = first;

}

}

public class Test07 {

public static void main(String[] args) {

Box<Integer> box1=new Box<>();

box1.setFirst(12);

showBox(box1);

}

 

public static void showBox(Box<?> box){

Object first = box.getFirst();

System.out.println(first);

}

}

类型通配符上限

语法

类/接口<?extends 实参类型>

要求该泛型的类型,只能是实参类型,或实参类型的子类类型

public class Test08 {

public static void main(String[] args) {

ArrayList<MinCat> minCats=new ArrayList();

ArrayList<Cat> cats=new ArrayList();

ArrayList<Animal> animals=new ArrayList<>();

showAnimal(minCats);

showAnimal(cats);

// showAnimal(animals); 会报错

}

 

public static void showAnimal(ArrayList<? extends Cat> list){

for (int i = 0; i < list.size(); i++) {

Cat cat = list.get(i);

System.out.println(cat);

}

}

}

 

类型通配符下限

语法

类/接口<?super 实参类型>

要求该泛型的类型,只能是实参类型,或实参类型的父类类型。

 

 

 

截图.png

 

截图.png

 

截图.png

截图.png

 

截图.png

多了一个info方法,擦除类型后

 

泛型数组

泛型数组的创建

可以声明带泛型的数组引用,但是不能直接创建带泛型的数组对象

//报错的写法

ArrayList<String>[] listArr=new ArrayList<>[5];

//正确的写法

ArrayList<String>[] listArr;

以下方式是有弊端的

public class Test10 {

public static void main(String[] args) {

ArrayList[] list=new ArrayList[5];

ArrayList<String>[] listArr=list;

 

ArrayList<Integer> intList=new ArrayList<>();

intList.add(100);

list[0]=intList;

String s = listArr[0].get(0);

System.out.println(s);

}

}

 

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

at com.itheima.demo10.Test10.main(Test10.java:13)

可以通过java.lang.reflect.Array的newInstance(Class<T>,int)创建T[]数组

import java.lang.reflect.Array;

 

public class Fruit <T>{

private T[] array;

 

public Fruit(Class<T> clz,int length) {

//通过Array.newInstance创建泛型数组

array = (T[])Array.newInstance(clz, length);

}

 

public void put(int index,T item){

array[index]=item;

}

 

public T get(int index){

return array[index];

}

 

public T[] getArray(){

return array;

}

}

 

截图.png

泛型与反射

反射常用的泛型类

Class<T>

Constructor<T>

 

public class Person {

private String name;

 

public String getName() {

return name;

}

 

public void setName(String name) {

this.name = name;

}

}

public class Test11 {

public static void main(String[] args) throws Exception {

Class<Person> personClass1 = Person.class;

Constructor<Person> constructor1 = personClass1.getConstructor();

Person person1 = constructor1.newInstance();

System.out.println(person1);

 

Class personClass2 = Person.class;

Constructor constructor2 = personClass2.getConstructor();

Object o = constructor2.newInstance();

System.out.println(o);

}

}