Java笔记(韩顺平Java基础15-20章)

Java学习笔记(第15章 P554-P568)(第16章P569-P579)(第17章P580-P599)(第18章P600-P610)(第19章P611-P644)(第20章P645-P661)

  • 第15章 泛型
    • 泛型的理解和好处
    • 泛型介绍
    • 泛型的语法
    • 泛型练习题
    • 自定义泛型
      • 自定义泛型类(难度)
      • 自定义泛型接口
      • 自定义泛型方法
    • 泛型的继承和通配符
    • JUnit
  • 第16章 坦克大战【1】
    • 坦克大战游戏演示
    • java绘图坐标体系
    • java事件处理机制
    • 坦克大战游戏
    • 本章作业
  • 第17章 多线程基础
    • 线程相关概念
    • 线程基本使用
    • 继承Thread vs 实现Runnable的区别
    • 线程终止
    • 线程常用方法
    • 线程的生命周期
    • 线程的同步
    • Synchronized
    • 分析同步原理
    • 互斥锁
    • 线程的死锁
    • 释放锁
  • 第18章坦克大战【2】
    • 线程 - 应用到坦克大战
  • 第19章 IO 流
    • 文件
    • 常见的文件操作
    • Io流原理及流的分类
    • IO 流体系图-常见的类
      • FileInputStream 应用实例
      • FileOutputStream介绍
    • 节点流和处理流
      • 打印流-PrintStream 和 PrintWriter
      • Properties类
  • 第20章坦克大战【3】
    • IO流-应用到坦克大战
  • 日期

第15章 泛型

泛型的理解和好处

  • 案例引出泛型
    Java笔记(韩顺平Java基础15-20章)_第1张图片

案例(传统方式解决):

package com.hspedu.generic;

import java.util.ArrayList;

@SuppressWarnings({
   "all"})
public class Generic01 {
   
    public static void main(String[] args) {
   

        //使用传统的方法来解决
        ArrayList arrayList = new ArrayList();
        arrayList.add(new Dog("旺财", 10));
        arrayList.add(new Dog("发财", 1));
        arrayList.add(new Dog("小黄", 5));

        //假如我们的程序员, 不小心, 添加了一只猫
        arrayList.add(new Cat("招财猫", 8));

        //遍历
        for (Object o : arrayList) {
   
            //向下转型Object -> Dog
            Dog dog = (Dog) o;
            System.out.println(dog.getName() + "-" + dog.getAge());
        }

    }
}
/*
请编写程序,在ArrayList 中,添加3个Dog对象
Dog对象含有name 和 age, 并输出name 和 age (要求使用getXxx())
 */

class Dog{
   
    private String name;
    private int age;

    public Dog(String name, int age) {
   
        this.name = name;
        this.age = age;
    }

    public String getName() {
   
        return name;
    }

    public void setName(String name) {
   
        this.name = name;
    }

    public int getAge() {
   
        return age;
    }

    public void setAge(int age) {
   
        this.age = age;
    }
}

class Cat{
     //Cat类
    private String name;
    private int age;

    public Cat(String name, int age) {
   
        this.name = name;
        this.age = age;
    }

    public String getName() {
   
        return name;
    }

    public void setName(String name) {
   
        this.name = name;
    }

    public int getAge() {
   
        return age;
    }

    public void setAge(int age) {
   
        this.age = age;
    }
}

结果:
程序出现类型转换的错误

  • 使用传统方法的问题分析
  1. 不能对加入到集合ArrayList中的数据类型进行约束(不安全)
    2)遍历的时候, 需要进行类型转换, 如果集合中的数据量较大,对效率有影响
  • 用泛型来解决前一案例
package com.hspedu.generic.improve;

import java.util.ArrayList;

@SuppressWarnings({
   "all"})
public class Generic02 {
   
   public static void main(String[] args) {
   
       //使用传统的方法来解决 ====>使用泛型
       //老韩解读
       //1. 当我们 ArrayList 表示存放到 ArrayList 集合中的元素是Dog类型 (细节后面说...)
       //2. 如果编译器发现添加的类型, 不满足要求, 就会报错
       //3. 在遍历的时候, 可以直接取出 Dog类型而不是 Object
       ArrayList<Dog> arrayList = new ArrayList<Dog>();
       arrayList.add(new Dog("旺财", 10));
       arrayList.add(new Dog("发财", 1));
       arrayList.add(new Dog("小黄", 5));

       //假如我们的程序员, 不小心, 添加了一只猫
       //arrayList.add(new Cat("招财猫", 8));

       System.out.println("===使用泛型===");
       for (Dog dog : arrayList) {
   
           System.out.println(dog.getName() + "-" + dog.getAge());
       }

   }
}

/*
1.请编写程序,在ArrayList 中,添加3个Dog对象
2.Dog对象含有name 和 age, 并输出name 和 age (要求使用getXxx())
3.老韩使用泛型来完成代码
*/

class Dog{
   
   private String name;
   private int age;

   public Dog(String name, int age) {
   
       this.name = name;
       this.age = age;
   }

   public String getName() {
   
       return name;
   }

   public void setName(String name) {
   
       this.name = name;
   }

   public int getAge() {
   
       return age;
   }

   public void setAge(int age) {
   
       this.age = age;
   }
}

class Cat{
     //Cat类
   private String name;
   private int age;

   public Cat(String name, int age) {
   
       this.name = name;
       this.age = age;
   }

   public String getName() {
   
       return name;
   }

   public void setName(String name) {
   
       this.name = name;
   }

   public int getAge() {
   
       return age;
   }

   public void setAge(int age) {
   
       this.age = age;
   }
}

  • 泛型的好处
    Java笔记(韩顺平Java基础15-20章)_第2张图片

泛型介绍

Java笔记(韩顺平Java基础15-20章)_第3张图片

案例:

package com.hspedu.generic;

public class Generic03 {
   
    public static void main(String[] args) {
   

        //注意,特别强调: E具体的数据类型在定义Person对象的时候指定,即在编译期间, 就确定E是什么类型
        Person<String>  person = new Person<String>("韩顺平教育");
        person.show();  //String
        /*
              你可以这样理解,上面的Person类
               class Person{
                    String s;

                    public Person(String s){
                        this.s = s;
                    }

                    public String f(){
                        return s;
                    }
                }
         */


    }
}

//泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,
// 或者是某个方法的返回值的类型,或者是参数类型

class Person<E>{
   
    E s;    //E表示 s的数据类型, 该数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型

    public Person(E s){
    //E也可以是参数类型
        this.s = s;
    }

    public E f(){
      //返回类型使用E
        return s;
    }

    public void show(){
   
        System.out.println(s.getClass());   //显示s的运行类型
    }
}



泛型的语法

  • 泛型的声明
    Java笔记(韩顺平Java基础15-20章)_第4张图片

  • 泛型的实例化

在这里插入图片描述

  • 泛型使用举例

Java笔记(韩顺平Java基础15-20章)_第5张图片

package com.hspedu.generic;

import java.util.*;

/**
 * @author zt
 * @version 1.0
 */
@SuppressWarnings({
   "all"})
public class GenericExercise {
   
    public static void main(String[] args) {
   
        //使用泛型方式给HashSet放入3个学生对象
        HashSet<Student> students = new HashSet<Student>();
        students.add(new Student("jack", 18));
        students.add(new Student("tom", 28));
        students.add(new Student("mary", 19));

        //遍历
        for(Student student : students){
   
            System.out.println(student);
        }

        //使用泛型方式给HashMap 放入3个学生对象
        //K -> String  V->Student
        HashMap<String, Student> hm = new HashMap<String, Student>();

        hm.put("milan", new Student("milan", 38));
        hm.put("smith", new Student("smith", 48));
        hm.put("hsp", new Student("hsp", 28));

        //迭代器 EntrySet
        /*
            public Set> entrySet() {
                Set> es;
                return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
            }
         */
        Set<Map.Entry<String, Student>> entries = hm.entrySet();
        /*
            public final Iterator> iterator() {
                    return new EntryIterator();
                }
         */
        Iterator<Map.Entry<String, Student>> iterator = entries.iterator();
        System.out.println("=================");
        while (iterator.hasNext()) {
   
            Map.Entry<String, Student> next =  iterator.next();
            System.out.println(next.getKey() + "-" + next.getValue());
        }
    }
}

/**
 * 创建  3个学生对象
 * 放入到HashSet中学生对象, 使用.
 * 放入到  HashMap中,要求 Key 是 String name, Value 就是 学生对象
 * 使用两种方式遍历
 */

class Student{
   
    private String name;
    private int age;

    public Student(String name, int age) {
   
        this.name = name;
        this.age = age;
    }

    public String getName() {
   
        return name;
    }

    public void setName(String name) {
   
        this.name = name;
    }

    public int getAge() {
   
        return age;
    }

    public void setAge(int age) {
   
        this.age = age;
    }

    @Override
    public String toString() {
   
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

  • 泛型使用的注意事项和细节

Java笔记(韩顺平Java基础15-20章)_第6张图片

泛型练习题

Java笔记(韩顺平Java基础15-20章)_第7张图片

代码实现:

main方法:

package com.hspedu.generic;

import java.util.ArrayList;
import java.util.Comparator;

@SuppressWarnings({
   "all"})
public class GenericExercise02 {
   
    public static void main(String[] args) {
   

        ArrayList<Employee> employees = new ArrayList<>();
        employees.add(new Employee("tom", 20000, new MyDate(2000,12,11)));
        employees.add(new Employee("jack", 12000, new MyDate(2001,12,12)));
        employees.add(new Employee("tom", 50000, new MyDate(2000,12,10)));

        System.out.println("employees=" + employees);


        employees.sort(new Comparator<Employee>() {
   
            @Override
            public int compare(Employee emp1, Employee emp2) {
   
                //先按照name排序,如果name相同,则按生日日期的先后排序。【即:定制排序】
                //先对传入的参数进行验证
                if(!(emp1 instanceof Employee && emp2 instanceof Employee)){
   
                    System.out.println("类型不正确..");
                    return 0;
                }

                //比较name
                int i = emp1.getName().compareTo(emp2.getName());
                if(i != 0){
   
                    return i;
                }

                //下面是对birthday的比较, 因此, 我们最好把比较, 放在MyDate类完成
                //封装后, 将来可维护性和复用性, 就大大增强
                return emp1.getBirthday().compareTo(emp2.getBirthday());
            }
        });

        System.out.println("==对雇员进行排序==");
        System.out.println(employees);
    }
}

/**
 * 定义Employee类
 * 1) 该类包含:private成员变量name,sal,birthday,其中 birthday 为 MyDate 类的对象;
 * 2) 为每一个属性定义 getter, setter 方法;
 * 3) 重写 toString 方法输出 name, sal, birthday
 * 4) MyDate类包含: private成员变量month,day,year;并为每一个属性定义 getter, setter 方法;
 * 5) 创建该类的 3 个对象,并把这些对象放入 ArrayList 集合中(ArrayList 需使用泛型来定义),对集合中的元素进行排序,并遍历输出:
 *
 * 排序方式: 调用ArrayList 的 sort 方法 ,
 * 传入 Comparator对象[使用泛型],先按照name排序,如果name相同,则按生日日期的先后排序。【即:定制排序】
 * 有一定难度 15min , 比较经典 泛型使用案例 GenericExercise02.java
 */


MyDate类

package com.hspedu.generic;


public class MyDate implements Comparable<MyDate>{
   
    private int year;
    private int month;
    private int day;

    public MyDate(int year, int month, int day) {
   
        this.year = year;
        this.month = month;
        this.day = day;
    }

    public int getYear() {
   
        return year;
    }

    public void setYear(int year) {
   
        this.year = year;
    }

    public int getMonth() {
   
        return month;
    }

    public void setMonth(int month) {
   
        this.month = month;
    }

    public int getDay() {
   
        return day;
    }

    public void setDay(int day) {
   
        this.day = day;
    }

    @Override
    public String toString() {
   
        return "MyDate{" +
                "year=" + year +
                ", month=" + month +
                ", day=" + day +
                '}';
    }

    @Override
    public int compareTo(MyDate o) {
       //把对year-month-day比较放在这里

        //如果name相同, 就比较 birthday - year
        int yearMinus = year - o.getYear();
        if(yearMinus != 0){
   
            return yearMinus;
        }

        //如果year相同, 就比较month
        int monthMinus = month - o.getMonth();
        if(monthMinus != 0){
   
            return monthMinus;
        }

        //如果year和month都相同, 就比较日
        return day - o.getDay();
    }
}

Employee类

package com.hspedu.generic;


public class Employee {
   
    private String name;
    private double sal;
    private MyDate birthday;

    public Employee(String name, double sal, MyDate birthday) {
   
        this.name = name;
        this.sal = sal;
        this.birthday = birthday;
    }

    public String getName() {
   
        return name;
    }

    public void setName(String name) {
   
        this.name = name;
    }

    public double getSal() {
   
        return sal;
    }

    public void setSal(double sal) {
   
        this.sal = sal;
    }

    public MyDate getBirthday() {
   
        return birthday;
    }

    public void setBirthday(MyDate birthday) {
   
        this.birthday = birthday;
    }

    @Override
    public String toString() {
   
        return "\nEmployee{" +
                "name='" + name + '\'' +
                ", sal=" + sal +
                ", birthday=" + birthday +
                '}';
    }
}

自定义泛型

自定义泛型类(难度)

Java笔记(韩顺平Java基础15-20章)_第8张图片

自定义泛型接口

Java笔记(韩顺平Java基础15-20章)_第9张图片

演示案例:

package com.hspedu.customgeneric;

public class CustomInterfaceGeneric {
   
    public static void main(String[] args) {
   

    }
}

/**
 *  泛型接口使用的说明
 *  1. 接口中, 静态成员也不能使用泛型
 *  2. 泛型接口的类型, 在继承接口或者实现接口时确定
 */

//在继承接口 指定泛型接口的类型
interface IA extends IUsb<String, Double>{
   

}

//当我们去实现IA接口时, 因为IA在继承IUsb接口时, 指定了U 为String R为 Double
//, 在实现IUsb接口的方法时, 使用String替换U, 是Double替换R
class AA implements  IA{
   

    @Override
    public Double get(String s) {
   
        return null;
    }

    @Override
    public void hi(Double aDouble) {
   

    }

    @Override
    public void run(Double r1, Double r2, String u1, String u2) {
   

    }
}

//实现接口时, 直接指定泛型接口的类型
//给U  指定Integer 给 R 指定了 Float
//所以, 当我们实现IUsb方法时, 会使用Integer替换U, 使用Float替换R
class BB implements IUsb<Integer, Float>{
   

    @Override
    public Float get(Integer integer) {
   
        return null;
    }

    @Override
    public void hi(Float aFloat) {
   

    }

    @Override
    public void run(Float r1, Float r2, Integer u1, Integer u2) {
   

    }
}

//没有指定类型, 默认为Object
//建议直接写成    IUsb
class CC implements IUsb {
          //等价 class CC implements IUsb
    @Override
    public Object get(Object o) {
   
        return null;
    }

    @Override
    public void hi(Object o) {
   

    }

    @Override
    public void run(Object r1, Object r2, Object u1, Object u2) {
   

    }


}

interface IUsb<U, R> {
   

    int n = 10;
    //U name;   不能这样使用

    //普通方法中,可以使用接口泛型
    R get(U u);

    void hi(R r);

    void run

你可能感兴趣的:(学习笔记,java,jvm,开发语言)