Java重温

(一)泛型(上)

1)No泛型
public class NeedGeneric1 {
    private static int add(int a, int b) {
        System.out.println(a + "+" + b + "=" + (a + b));
        return a + b;
    }

    private static float add(float a, float b) {
        System.out.println(a + "+" + b + "=" + (a + b));
        return a + b;
    }

    private static double add(double a, double b) {
        System.out.println(a + "+" + b + "=" + (a + b));
        return a + b;
    }

    private static <T extends Number> double add(T a, T b) {
        System.out.println(a + "+" + b + "=" + (a.doubleValue() + b.doubleValue()));
        return a.doubleValue() + b.doubleValue();
    }

    public static void main(String[] args) {
        NeedGeneric1.add(1, 2);
        NeedGeneric1.add(1f, 2f);
        NeedGeneric1.add(1d, 2d);
        NeedGeneric1.add(Integer.valueOf(1), Integer.valueOf(2));
        NeedGeneric1.add(Float.valueOf(1), Float.valueOf(2));
        NeedGeneric1.add(Double.valueOf(1), Double.valueOf(2));
    }
}

我们不难发现,同一个add方法,我们需要写要几个不同参数形式的方法去适配所有的情况,这无疑是十分不方便的。

2)Have泛型
package com.jay.java.泛型.DefineGeneric;

public class GenericClass<T> {
    private T data;

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public static void main(String[] args) {
        GenericClass<String> genericClass=new GenericClass<>();
        genericClass.setData("Generic Class");
        System.out.println(genericClass.getData());
    }
}
3)泛型的意义
  1. 适用于多种数据类型执行相同的代码(代码复用)
  2. 泛型中的类型在使用时指定,不需要强制类型转换(类型安全,编译器会检查类型)
4)视频部分代码

泛型Car

package lys.genericityup.Bean;

public class Car <T>{
    private T car;

    public Car(T car){
        this.car = car;
    }

    public T getObject() {
        return this.car;
    }
}

测试方法

package lys.genericityup.test;

import lys.genericityup.Bean.Car;
import org.junit.Test;

import java.util.Date;

public class TestMain {

    @Test
    public void testCar(){
        Car<String> car = new Car<>("Bus");
        System.out.println(car.getObject());

        Car<Date> car2 = new Car<Date>(new Date());
        System.out.println(car2.getObject());

    }
}

(二)泛型(下)

1) 泛型的继承规则
  1. 对于泛型参数是继承关系的泛型类之间是没有继承关系的
  2. 泛型类可以继承其它泛型类,例如: public class Car<T> extends Vehicle<T>
  3. 泛型类的继承关系在使用中同样会受到泛型类型的影响
2)视频中部分代码

Car类

package lys.genericitydown.bean;

public class Car<T> extends Vehicle<T>{

    public Car(T name) {
        super(name);
    }
}

Vehicle类

package lys.genericitydown.bean;

public class Vehicle<T> {
    private T name;

    public Vehicle(T name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Vehicle{" +
                "name=" + name +
                '}';
    }
}

Test类

package lys.genericitydown.test;

import lys.genericitydown.bean.Car;
import org.junit.Test;

import javax.xml.crypto.Data;
import java.util.Date;

public class TestMain {
    @Test
    public void test01(){
        System.out.println(new Car<String>("BMW").toString());

    }

}
3) 泛型的通配符问题
  1. <? extends Parent>指定了泛型类型的上级
  2. <? super Child>指定了泛型类型的下级
  3. <?>指定了没有限制的泛型类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eoSS6jbf-1584538429218)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\1584536788750.png)]

4)参考代码
public class GenericByWildcard {
    private static void print(GenericClass<Fruit> fruitGenericClass) {
        System.out.println(fruitGenericClass.getData().getColor());
    }

    private static void use() {
        GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
        print(fruitGenericClass);
        GenericClass<Orange> orangeGenericClass = new GenericClass<>();
        //类型不匹配,可以使用<? extends Parent> 来解决
//        print(orangeGenericClass);
    }

    /**
     * <? extends Parent> 指定了泛型类型的上届
     */
    private static void printExtends(GenericClass<? extends Fruit> genericClass) {
        System.out.println(genericClass.getData().getColor());
    }

    public static void useExtend() {
        GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
        printExtends(fruitGenericClass);
        GenericClass<Orange> orangeGenericClass = new GenericClass<>();
        printExtends(orangeGenericClass);

        GenericClass<Food> foodGenericClass = new GenericClass<>();
        //Food是Fruit的父类,超过了泛型上届范围,类型不匹配
//        printExtends(foodGenericClass);

        //表示GenericClass的类型参数的上届是Fruit
        GenericClass<? extends Fruit> extendFruitGenericClass = new GenericClass<>();
        Apple apple = new Apple();
        Fruit fruit = new Fruit();
        /*
         * 道理很简单,? extends X  表示类型的上界,类型参数是X的子类,那么可以肯定的说,
         * get方法返回的一定是个X(不管是X或者X的子类)编译器是可以确定知道的。
         * 但是set方法只知道传入的是个X,至于具体是X的那个子类,不知道。
         * 总结:主要用于安全地访问数据,可以访问X及其子类型,并且不能写入非null的数据。
         */
//        extendFruitGenericClass.setData(apple);
//        extendFruitGenericClass.setData(fruit);

        fruit = extendFruitGenericClass.getData();

    }

    /**
     * <? super Child> 指定了泛型类型的下届
     */
    public static void printSuper(GenericClass<? super Apple> genericClass) {
        System.out.println(genericClass.getData());
    }

    public static void useSuper() {
        GenericClass<Food> foodGenericClass = new GenericClass<>();
        printSuper(foodGenericClass);

        GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
        printSuper(fruitGenericClass);

        GenericClass<Apple> appleGenericClass = new GenericClass<>();
        printSuper(appleGenericClass);

        GenericClass<HongFuShiApple> hongFuShiAppleGenericClass = new GenericClass<>();
        // HongFuShiApple 是Apple的子类,达不到泛型下届,类型不匹配
//        printSuper(hongFuShiAppleGenericClass);

        GenericClass<Orange> orangeGenericClass = new GenericClass<>();
        // Orange和Apple是兄弟关系,没有继承关系,类型不匹配
//        printSuper(orangeGenericClass);

        //表示GenericClass的类型参数的下界是Apple
        GenericClass<? super Apple> supperAppleGenericClass = new GenericClass<>();
        supperAppleGenericClass.setData(new Apple());
        supperAppleGenericClass.setData(new HongFuShiApple());
        /*
         * ? super  X  表示类型的下界,类型参数是X的超类(包括X本身),
         * 那么可以肯定的说,get方法返回的一定是个X的超类,那么到底是哪个超类?不知道,
         * 但是可以肯定的说,Object一定是它的超类,所以get方法返回Object。
         * 编译器是可以确定知道的。对于set方法来说,编译器不知道它需要的确切类型,但是X和X的子类可以安全的转型为X。
         * 总结:主要用于安全地写入数据,可以写入X及其子类型。
         */
//        supperAppleGenericClass.setData(new Fruit());

        //get方法只会返回一个Object类型的值。
        Object data = supperAppleGenericClass.getData();
    }

    /**
     * <?> 指定了没有限定的通配符
     */
    public static void printNonLimit(GenericClass<?> genericClass) {
        System.out.println(genericClass.getData());
    }

    public static void useNonLimit() {
        GenericClass<Food> foodGenericClass = new GenericClass<>();
        printNonLimit(foodGenericClass);
        GenericClass<Fruit> fruitGenericClass = new GenericClass<>();
        printNonLimit(fruitGenericClass);
        GenericClass<Apple> appleGenericClass = new GenericClass<>();
        printNonLimit(appleGenericClass);

        GenericClass<?> genericClass = new GenericClass<>();
        //setData 方法不能被调用, 甚至不能用 Object 调用;
//        genericClass.setData(foodGenericClass);
//        genericClass.setData(new Object());
        //返回值只能赋给 Object
        Object object = genericClass.getData();

    }

}
5)泛型中的约束和局限性
  1. 不能实例化泛型类
  2. 静态变量或方法不能引用泛型类型变量,但是静态泛型方法是可以的
  3. 基本类型无法作为泛型类型
  4. 无法使用 instanceof 关键字或==判断泛型类的类型
  5. 泛型类的原生类型与所传递的泛型无关,无论传递什么类型,原生类是一样的
  6. 泛型数组可以声明但无法实例化
  7. 泛型类不能继承Exception或者Throwable
  8. 不能捕获泛型类型限定的异常但可以将泛型限定的异常抛出

(三) Collection

1)List
 @org.junit.Test
    public void test01(){
        List list = new ArrayList();
        list.add(10);
        list.add("hello");
        list.add(true);
        list.add(99.9f);
        /*
        第一种遍历方法
        */
        for (Object o : list) {
            System.out.println(o);
        }
        /*
        第二中遍历方法
        */
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            Object next = iterator.next();
            System.out.println(next);
        }
    }

2)HashSet

HashSet中没有重复的元素,可以用于去重

@org.junit.Test
    public void test02(){
        /**
         * HashSet中没有重复的元素
         */
        Set set = new HashSet();
        set.add(1);
        set.add("Hello");
        set.add(1246.4f);
        set.add("Hello");
        for (Object o : set) {
            System.out.println(o);
        }
    }
3) Queue
@org.junit.Test
    public void test03(){
        /**
         * 不要使用add方法添加
         * 相同:两者都是往队列尾部插入元素,
         * 不同的:当超出队列界限的时候,add()方法是抛出异常让你处理,而offer()方法是直接返回false
         */
        Queue queue = new LinkedList<>();
        queue.offer(1);
        queue.offer("Hello");
        queue.offer(999.9d);
        for (Object o : queue) {
            System.out.println(o);
        }
        /**
         * peek()方法会返回队列的头部
         */
        System.out.println("QueueHead:"+queue.peek());
        System.out.println("QueueSize:"+queue.size());

        /**
         * poll()会把队列的头部取出
         */
        System.out.println("QueueHead:"+queue.poll());
        System.out.println("QueueSize:"+queue.size());


    }
4)HashMap
@org.junit.Test
    public void test04(){
        /*
       	添加键值对到map中去
        */
        Map<String,String> map = new HashMap<String,String>();
        map.put("1a","Hello");
        map.put("2b","World");
        map.put("3c","Java");
        /*
        遍历方法一:
        	只获取出map中的values
        */
        System.out.println("打印Values");
        for (String value : map.values()){
            System.out.println(value);
        }
        System.out.println("============================");
        /*
        遍历方法二:
        	获取出map中的key和value
        */
        System.out.println("打印Key:Value");
        Set<String> set = map.keySet();
        for (String key : set) {
            String value = map.get(key);
            System.out.println(key+":"+value);
        }
        System.out.println("============================");
        /*
        遍历方法三:
        	最常用的方法
        */
        System.out.println("最常用的方式打印");
        for (Map.Entry<String, String> entry : map.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key+":"+value);
        }
    }
5)Array
@org.junit.Test
    public void test05(){
        /**
         * 一旦转换是不能修改的
         */
        List list = Arrays.asList(1,2,3,4,5,6,7,8,9);
        for (Object o : list) {
            System.out.println(o);
        }

        System.out.println("List转换为数组");
        Object[] objects = list.toArray();
        System.out.println(Arrays.toString(objects));

        /**
         * 把List转换为不能更改的List
         */

        ArrayList<Object> list2 = new ArrayList<>();
        list2.add(1);
        list2.add(2);
        List<Object> unlist = Collections.unmodifiableList(list2);
        /**
         * unlist不能更改
         */

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值