zoukankan      html  css  js  c++  java
  • 第三节:高级知识

    1. 异常处理

    1.1 异常层次结构

    • 所有异常类都是java.lang.Exception类的子类型。

    • Exception类是Throwable类的子类。还有另一个名称为Error的子类,它派生自Throwable

    • Exception类有两个主要的子类:IOException类和RuntimeException

    1.2 异常方法

    以下是Throwable类中可用的方法列表:

    方法 描述
    String getMessage() 返回有关已发生的异常的详细消息
    Throwable getCause() 返回由Throwable对象表示的异常的原因
    String toString() 返回与getMessage()结果连接的类名称
    void printStackTrace() toString()的结果与堆栈跟踪一起打印到System.err(错误输出流)

    1.3 捕捉异常

    使用规则

    • 没有try语句就不能存在catch子句
    • 只要存在try/catch块,finally子句就不是必须的
    • 如果没有catch子句或finally子句,则try块不能出现
    • trycatchfinally块之间不能出现任何代码

    在方法中可使用trycatch关键字的组合捕获异常,将容易出现异常的代码放在try块中。 发生异常时,异常由与其关联的catch块处理。 每个try块都应该紧跟一个catch块或者一个块finally

    基本语法

    try {
       // Protected code
    } catch (ExceptionName e1) {
       // Catch block
    }
    

    监听多种异常

    如果抛出的异常的数据类型与ExceptionType1匹配,则会在那里捕获它,如果不是,则异常传递给第二个catch语句

    try {
       // Protected code
    } catch (ExceptionName e1) {
       // Catch block
    } catch (ExceptionName e2) {
       // Catch block
    }
    

    finally 语句

    finally块在try块或catch块之后,无论受保护的代码块是否发生异常,最终都会执行finally块中的代码

    try {
       // Protected code
    } catch (ExceptionType1 e1) {
       // Catch block
    } catch (ExceptionType2 e2) {
       // Catch block
    } catch (ExceptionType3 e3) {
       // Catch block
    }finally {
       // The finally block always executes.
    }
    

    finally 语句块种有reutrn语句时,返回值为finally语句快的返回值

    private static int Reu() {
        try {
            return 1;
        }catch(Exception e) { 
            return 2;
        }finally {
            return 3;	/* 不应在此语句块种有 return 语句*/
        }
    }
    

    try-with-resources 语句

    • 使用带有try-with-resources语句的类,它应该实现AutoCloseable接口,并且它的close()方法在运行时自动调用
    • try块声明的资源被隐式声明为final

    通常,当使用流,连接等任何资源时,要使用finally块显式关闭它们,try-with-resources自动关闭try/catch块中使用的资源

    try(FileReader fr = new FileReader("file path")) {
       // use the resource
       } catch () {
          // body of catch 
       }
    }
    

    1.4 声明/抛出异常

    • 如果一个方法没有捕获一个检查性异常,那么该方法必须使用 throws 关键字来声明

    • throws 关键字放在方法签名的尾部

    • 使用 throw 关键字抛出一个异常,无论它是新实例化的还是刚捕获到的

    • 当抛出异常时可以抛出定义的异常或是它的父类

    抛出异常

    // 处理异常
    public static void main(String[] args) {
        try {
            withdraw(2);
        } catch (RemoteException e) {
            // TODO: handle exception
        }
    }
    
    // 抛出异常
    public static void withdraw(double amount) throws RemoteException{
        throw new RemoteException();
    }
    

    抛出多个异常

    一个方法可以声明抛出多个异常,多个异常之间用逗号隔开

    public void withdraw(double amount) throws RemoteException,ArrayStoreException
        // Method implementation
        throw new RemoteException();
    }
    

    抛出异常父类

    当抛出异常父类时,不管有没有监听异常字类,一定要有监听父类异常

    public static void main(String[] args) {
        try {
            withdraw(2);
        } catch (RemoteException e) {
            // TODO: handle exception
        }catch(Exception ex) {
            // TODO: handle exception
        }
    }
    
    public static void withdraw(double amount) throws Exception{
        throw new Exception();
    }
    
    public static void withdraw(double amount) throws RemoteException{
        throw new RemoteException();
    }
    

    1.5 自定义异常

    • 所有异常都必须是 Throwable 的子类
    • 如果希望写一个检查性异常类,则需要继承 Exception
    • 如果你想写一个运行时异常类,那么需要继承 RuntimeException

    定义异常

    public class CustomException extends Exception {
        private String Message;
    	public CustomException(String ExceptionMsg) {
            this.Message = ExceptionMsg;
    		super("自定义错误"+Message);
    	}
    }
    

    抛出异常

    public static void withdraw(double amount) throws CustomException{
        throw new CustomException("错误");
    }
    

    监听异常

    public static void main(String[] args) {
        try {
            withdraw(1);
        } catch (CustomException e) {
            System.out.println(e.getMessage());
        }
    }
    

    1.6 异常链

    异常链:将异常发生的原因一个传一个的连起来,即把底层的异常信息传给上层,逐层抛出

    public class exp {
    	public static void main(String[] args) {
    		try {
    			Fun2();
    		} catch (Exception e) {
    			System.out.println(e.getMessage());
    		}
    	}
    	public static void Fun1() throws Exception{
    		throw new Exception("Fun1");
    	}
    	public static void Fun2() throws Exception{
    		try {
    			Fun1();
    		} catch (Exception e) {
    			throw new Exception("Fun2",e);
    		}
    	}
    }
    

    2. 字符串操作

    2.1 String

    字符串方法

    方法 描述
    int length() 返回字符串长度
    String concat(String str) 连接两个字符串,返回连接后的字符串

    格式化字符串

    String fs = String.format("浮点型变量的值为 " +
    "%f, 整型变量的值为 " +
    " %d, 字符串变量的值为 " +
    " %s", floatVar, intVar, stringVar);
    

    2.2 StringBuffer

    StringBuffer 类的对象能够被多次的修改,并且不产生新的未使用对象

    线程安全的情况下,则必须使用 StringBuffer

    public class Test{
        public static void main(String args[]){
            StringBuffer sBuffer = new StringBuffer(":");
            sBuffer.append("1");
            sBuffer.append("2");
            sBuffer.append("3");
            System.out.println(sBuffer);
        }
    }
    

    2.3 StringBuilder

    StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象

    StringBuilder 的方法不是线程安全的(不能同步访问)

    public class Test {
    	public static void main(String[] args) {
    		StringBuilder str1 = new StringBuilder("");
    		System.out.println(str1 + "	" + str1.hashCode());
    		str1 = str1.append("libai");
    		System.out.println(str1 + "	" + str1.hashCode());
    		str1 = str1.append("zhanyun");
    		System.out.println(str1 + "	" + str1.hashCode());
    	}
    }
    

    3. 数值操作

    3.1 Math

    JavaMath 包含了用于执行基本数学运算的属性和方法,如初等指数、对数、平方根和三角函数。方法都被定义为 static 形式,通过 Math 类可以在主函数中直接调用

    Number & Math 类常用的一些方法:

    方法 描述
    double floor() 对一个数进行下舍入,返回给定参数最大的整数,该整数小于或等给定的参数
    double ceil() 对一个数进行上舍入,返回值大于或等于给定的参数的最小整数
    longround() 将原来的数字加上 0.5 后再向下取整,返回最大的整数,长整型

    4. 日期时间

    4.1 Java Date

    java.util 包提供了 Date 类来封装当前的日期和时间

    构造函数,初始化Date对象

    使用当前日期和时间来初始化对象

    Date date = new Date();
    

    接收一个参数,该参数是从1970年1月1日起的毫秒数

    Date date = new Date(long millisec)
    

    方法列表

    方法名 描述
    boolean after(Date date) 调用此方法的Date对象在指定日期之后,是返回true
    boolean before(Date date) 调用此方法的Date对象在指定日期之前,是返回true
    boolean equals(Object date) 调用此方法的Date对象和指定日期相等时候返回true
    long getTime( ) 返回此 Date 对象表示的毫秒数
    void setTime(long time) 毫秒数设置时间和日期

    使用 SimpleDateFormat 格式化日期

    使用方式:

    Date date = new Date();
    SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
            
    String datetime = ft.format(date);
    

    常用格式:

    格式 示例
    y 四位年份
    M 月份
    H 小时 (0~23)
    h 小时(1~12)
    m 分钟数
    s 秒数
    S 毫秒数
    d 一个月的日期
    E 星期几
    W 一个月中第几周
    F 一个月中第几周的周几
    D 一年中的日子
    w 一年中第几周

    解析字符串为时间对象

    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class Demo1DateTime {
        public static void main(String[] args) throws ParseException {
            String date_str = "2021-03-26 23:15:05";
            
            SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            
            Date date = ft.parse(date_str);
            System.out.println(date.toLocaleString());
        }
    }
    

    4.2 Java Calendar

    导入import java.util.Calendar;

    • Calender的月份是从0开始的,但日期和年份是从1开始的

    创建日期对象

    当前日期:

    Calendar c = Calendar.getInstance();// 默认是当前日期
    

    指定日期:

    Calendar c1 = Calendar.getInstance();	// 创建Calendar对象
    c1.set(2021,5,12);	// 设置日期
    

    设置日期(set

    参数设置:

    public final void set(int year,int month,int date)
    
    Calendar c1 = Calendar.getInstance();	// 创建Calendar对象
    c1.set(2021,5,12);	// 设置日期
    

    利用字段类型设置:

    Calendar c1 = Calendar.getInstance();	// 创建Calendar对象
    c.set(Calendar.YEAR, 1999);	// 设置年份,没有设置的默认当前日期时间
    
    常量 描述
    Calendar.YEAR 年份
    Calendar.MONTH 月份
    Calendar.DATE 日期
    Calendar.DAY_OF_MONTH 日期,和上面的字段意义完全相同
    Calendar.HOUR 12小时制的小时
    Calendar.HOUR_OF_DAY 24小时制的小时
    Calendar.MINUTE 分钟
    Calendar.SECOND
    Calendar.DAY_OF_WEEK 星期几

    设置日期(add

    Calendar c1 = Calendar.getInstance();	// 初始化对象,默认当前日期时间
    
    c1.add(Calendar.DATE, 1);	// 天数加 1
    c1.add(Calendar.DATE, 1);	// 天数减 1
    /* 其他字段属性的add的意义以此类推 */
    

    获取日期时间(get

    Calendar c1 = Calendar.getInstance();
    // 获得年份
    int year = c1.get(Calendar.YEAR);
    // 获得月份
    int month = c1.get(Calendar.MONTH) + 1;
    // 获得日期
    int date = c1.get(Calendar.DATE);
    // 获得小时
    int hour = c1.get(Calendar.HOUR_OF_DAY);
    // 获得分钟
    int minute = c1.get(Calendar.MINUTE);
    // 获得秒
    int second = c1.get(Calendar.SECOND);
    // 获得星期几(注意(这个与Date类是不同的):1代表星期日、2代表星期1、3代表星期二,以此类推)
    int day = c1.get(Calendar.DAY_OF_WEEK);
    

    5. 集合框架

    集合框架体系结构

    • 集合框架位于java.util包中, 所以当使用集合框架的时候需要进行导包

    5.1 集合接口

    接口 描述
    Collection 接口 最基本的集合接口,一个Collection 代表一组Object,即Collection的元素;不提供直接继承自Collection的类,只提供继承于的子接口(如Listset)
    List 接口 是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引访问List中的元素,允许有相同的元素
    Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素
    SortedSet 继承于Set保存有序的集合
    Map 将唯一的键映射到值
    SortedMap 继承于Map,使Key保持在升序排列

    5.2 标准集合类

    类名 描述
    AbstractCollection 实现了大部分的集合接口
    AbstractList 继承于AbstractCollection 并且实现了大部分List接口
    AbstractSequentialList 继承于 AbstractList ,提供了对数据元素的链式访问而不是随机访问
    LinkedList 实现了List接口,允许有null(空)元素。主要用于创建链表数据结构,该类没有同步方法,如果多个线程同时访问一个List,则必须自己实现访问同步,解决方法就是在创建List时候构造一个同步的List,LinkedList 查找效率低
    ArrayList 实现了List的接口,实现了可变大小的数组,随机访问和遍历元素时,提供更好的性能。该类也是非同步的,在多线程的情况下不要使用
    AbstractSet 继承于AbstractCollection 并且实现了大部分Set接口
    HashSet 实现了Set接口,不允许出现重复元素,不保证集合中元素的顺序,允许包含值为null的元素,但最多只能一个
    TreeSet 实现了Set接口,可以实现排序等功能
    AbstractMap 实现了大部分的Map接口
    HashMap 实现了Map接口,根据键的HashCode值存储数据,具有很快的访问速度,最多允许一条记录的键为null,不支持线程同步
    TreeMap 继承了AbstractMap,并且使用一颗树

    5.3 Iterator 迭代器

    Java Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,可用于迭代 ArrayList 和 HashSet 等集合

    引用

    Iterator 类位于 java.util 包中,使用前需要引入它,语法格式如下:

    import java.util.Iterator; // 引入 Iterator 类
    

    操作示例

    迭代器是有状态的,迭代器会逐个迭代集合中的元素,且会记录当前的位置

    / 引入 ArrayList 和 Iterator 类
    import java.util.ArrayList;
    import java.util.Iterator;
    
    public class RunoobTest {
        public static void main(String[] args) {
            ArrayList<Integer> numbers = new ArrayList<Integer>();
            numbers.add(12);
            numbers.add(8);
            numbers.add(2);
            numbers.add(23);
            Iterator<Integer> it = numbers.iterator();	// 1.获取迭代器对象
            while(it.hasNext()) {	// 2.检测集合中是否还有元素
                Integer i = it.next();	// 3.获取下一个元素,并且更新迭代器的状态
                if(i < 10) {  
                    it.remove();  // 4.将迭代器返回的元素删除
                }
            }
            System.out.println(numbers);
        }
    }
    

    5.4 ArrayList

    ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,可以添加或删除元素;继承了 AbstractList ,并实现了 List 接口

    操作方法

    方法名 描述 返回值
    add([int index,]E element) 将元素插入到[指定位置的]数组 成功,返回 true
    addAll([int index,]Collection c) 将给定集合中所有元素插入到[指定位置的]数组 成功,返回 true
    clear() 清空数组
    clone() 用于拷贝一份动态数组,属于浅拷贝 ArrayList 对象
    isEmpty() 判断动态数组是否为空 空,返回 true
    subList(int start_i, int end_i) 截取一段,[起始位置,结束位置) ArrayList 对象
    contains(Object obj) 判断元素是否在动态数组中 是,返回 true
    get(int index) 通过索引值获取动态数组中的元素 索引元素
    removeAll(Collection c) 删除存在于指定集合中的动态数组元素 成功,返回 true
    remove(Object obj/int index) 用于删除动态数组里的单个元素 成功,返回 true
    set(int index, E element) 修改动态数组中指定索引的元素 返回修改前元素
    sort(Comparator c) 排序
    removeIf(Lambda lab) 删除所有满足特定条件的数组元素 成功,返回 true
    forEach(Consumer action) 遍历动态数组中每一个元素

    声明集合

    ArrayList 类位于 java.util 包中,使用前需要引入它,语法格式如下:

    • E: 泛型数据类型,用于设置 objectName 的数据类型,只能为引用数据类型
    import java.util.ArrayList; // 引入 ArrayList 类
    
    ArrayList<E> objectName =new ArrayList<>();  // 初始化
    List list1 = new ArrayList();
    List<String> list2 = new ArrayList<String>();
    

    操作集合元素

    package day2;
    
    import java.util.*;
    
    public class MATH {
    	public static void main(String[] args) {
    	    List list1 = new ArrayList();
            list1.add("赵云");
            System.out.println(list1.get(0));
            list1.set(0, "赵云2");
            System.out.println(list1.get(0));
            list1.remove(0);
            System.out.println(list1.size());
            
            List<String> list2 = new ArrayList<String>();
            list2.add("李白");
            System.out.println(list2.get(0));
            list2.set(0, "李白2");
            System.out.println(list2.get(0));
            list2.remove(0);
            System.out.println(list2.size());
    	}
    }
    

    如果要存储其他类型,而 <E> 只能为引用数据类型,这时我们就需要使用到基本类型的包装类

    ArrayList<Integer> li=new Arraylist<>();     // 存放整数元素
    ArrayList<Character> li=new Arraylist<>();   // 存放字符元素
    

    示例:使用 ArrayList 存储数字(使用 Integer 类型)

    import java.util.ArrayList;
    
    public class RunoobTest {
        public static void main(String[] args) {
            ArrayList<Integer> myNumbers = new ArrayList<Integer>();
            myNumbers.add(10);
            myNumbers.add(15);
            for (int i : myNumbers) {
                System.out.println(i);
            }
        }
    }
    

    删除筛选过的元素

    removeIf() 方法用于删除所有满足特定条件的数组元素

    import java.util.*;
    
    class Main {
        public static void main(String[] args){
            // 创建一个动态数组
            ArrayList<String> sites = new ArrayList<>();
           
            sites.add("Google");
            sites.add("Runoob");
            sites.add("Taobao");
            
            // 删除名称中带有 Tao 的元素
            sites.removeIf(e -> e.contains("Tao"));
        }
    }
    

    遍历集合元素

    第一种方式:使用增强for循环

    package day2;
    
    import java.util.*;
    
    public class MATH {
        public static void main(String[] args) {
            List list1 = new ArrayList();
            list1.add("赵云");
            System.out.println(list1.get(0));
            list1.set(0, "赵云2");
            System.out.println(list1.get(0));
            list1.remove(0);
            System.out.println(list1.size());
    
            List<String> list2 = new ArrayList<String>();
            list2.add("李白"); // 添加:添加到末尾
            list2.add(0, "李白2"); // 添加:添加到指定索引除
            System.out.println(list2.get(0) + "	" + list2.get(1));
            list2.set(0, "李白"); // 修改:第一个参数为索引位置,第二个为要修改的值
            System.out.println(list2.get(0) + "	" + list2.get(1));
            list2.remove(0);
            System.out.println(list2.size());
        }
    }
    

    第二种方式:使用普通for 循环

    package day2;
    
    import java.util.*;
    
    public class MATH {
    
    	public static void main(String[] args) {
    		List list1 = new ArrayList();
    		list1.add("赵云");
    		for (int i = 0; i < list1.size(); i++) {
    			System.out.println(list1.get(i));
    		}
    		
    		List<String> list2 = new ArrayList<String>();
    		list2.add("李白");
    		for (int i = 0; i < list2.size(); i++) {
    			System.out.println(list2.get(i));
    		}
    	}
    }
    

    第三种方式:使用迭代器进行相关遍历

    package day2;
    
    import java.util.*;
    
    public class MATH {
    
    	public static void main(String[] args) {
    		List list1 = new ArrayList();
    		list1.add("赵云");
    		Iterator<String> ite = list1.iterator();
    		while (ite.hasNext())// 判断下一个元素之后有值
    		{
    			System.out.println(ite.next());
    		}
    
    		List<String> list2 = new ArrayList<String>();
    		list2.add("李白");
    		Iterator<String> ite2 = list2.iterator();
    		while (ite2.hasNext())// 判断下一个元素之后有值
    		{
    			System.out.println(ite2.next());
    		}
    	}
    }
    

    第四种方式:使用forEach 方法

    package day2;
    import java.util.*;
    
    public class MATH {
        public static void main(String[] args) {
            // 创建一个数组
            ArrayList<Integer> numbers = new ArrayList<>();
    
            // 往数组中添加元素
            numbers.add(1);
            numbers.add(2);
            numbers.add(3);
            numbers.add(4);
    
            // 将 lambda 表达式传递给 forEach
            numbers.forEach((e) -> {
                e = e * 10;
                System.out.print(e + " ");
            });
        }
    }
    

    5.5 HashMap

    HashMap 是一个散列表,继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口<它存储的内容是键值对(key-value)映射,且元素是无序的;实现了 Map 接口,根据键的 HashCode 值存储数据;最多允许一条记录的键为 null,不支持线程同步;

    操作方法

    方法 描述 返回值
    put(K k,V v) 键不存在添加/存在修改键值 存在,返回旧的value值,反之返回null
    putIfAbsent(K k,V v) 判断键是否存在,不存在添加 存在,返回旧的value值,反之返回null
    remove(K k[,V v]) 移除键【,值】对应元素 key存在,成功返回value值,反正返回null;
    value存在,成功返回true,反正返回false
    get(K k) 返回指定键值 key存在,成功返回value值,反正返回null
    getOrDefault(K k,V dv) 返回指定键值 key存在,成功返回value值,反正返回默认值
    size() 返回数量 集合为空则抛出异常

    声明

    HashMap 类位于 java.util 包中,使用前需要引入它,语法格式如下:

    import java.util.HashMap; // 引入 HashMap 类
    
    HashMap<Integer, String> Sites = new HashMap<Integer, String>();
    

    操作示例

    package day2;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class HashMapTest {
    
        public static void main(String[] args) {
            Map<Integer, String> SitesMap = new HashMap<Integer, String>();
            SitesMap.put(1, "Google");  // 添加:添加元素(key,value)
            SitesMap.put(2, "Runoob");
            
            System.out.println(SitesMap.get(2));    // 根據key值获取元素,Google
            
            SitesMap.remove(2); // 移除,根据key移除元素
            
            int size = SitesMap.size(); // 获取元素数量
            
            SitesMap.clear();   // 清空所有元素
            
            System.out.println(SitesMap);
            
            
            HashMap<Integer, String> Sites = new HashMap<Integer, String>();
            Sites.put(1, "Google");
            Sites.put(2, "Runoob");
            
            System.out.println(Sites.get(1));
            
            System.out.println(Sites);
        }
    
    }
    

    遍历HashMap

    第一种:使用增强for 遍历

    package day2;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class HashMapTest {
    
        public static void main(String[] args) {
            Map<Integer, String> SitesMap = new HashMap<Integer, String>();
            SitesMap.put(1, "Google");
            SitesMap.put(2, "Runoob");
            
            // 输出 key 和 value
            for (Integer i : SitesMap.keySet()) {
                System.out.println("key: " + i + " value: " + Sites.get(i));
            }
            // 返回所有 value 值
            for(String value: SitesMap.values()) {
              // 输出每一个value
              System.out.print(value + ", ");
            }
            
            HashMap<Integer, String> Sites = new HashMap<Integer, String>();
            Sites.put(1, "Google");
            Sites.put(2, "Runoob");     
            // 输出 key 和 value
            for (Integer i : Sites.keySet()) {
                System.out.println("key: " + i + " value: " + Sites.get(i));
            }
            // 返回所有 value 值
            for(String value: Sites.values()) {
              // 输出每一个value
              System.out.print(value + ", ");
            }
        }
    }
    

    第二种:使用forEach()方法

    import java.util.HashMap;
    
    public class HashMapTest {
    
        public static void main(String[] args) {
            HashMap<Integer, String> Sites = new HashMap<Integer, String>();
            Sites.put(1, "Google");
            Sites.put(2, "Runoob");
    
            Sites.forEach((key, value) -> {
                System.out.println(key + "	" + value);
            });
        }
    }
    

    5.6 HashSet

    5.7 数组排序

    数值数组排序(Comparator接口)

    按照数值大小排序

    List<Integer> list = new ArrayList<Integer>();
    ...
    Collections.sort(list);
    

    字符串排序(Comparator接口)

    按照国际编码排序

    List<String> list = new ArrayList<String>();
    ...
    Collections.sort(list);
    

    自定义类型排序(Comparator接口)

    对任意类型集合对象进行整体排序,排序时将此接口的实现传递给Collections.sort方法或者Arrays.sort方法排序.实现int compare(T o1, T o2);方法,返回正数,零,负数各代表大于,等于,小于

    条件排序:自定义比较器类

    package day3;
    
    import java.util.Comparator;
    /**
     * 比较器类
     */
    public class CustomComparator implements Comparator<UserInfo> {
    
        @Override
        public int compare(UserInfo o1, UserInfo o2) {
            // 升序
            //return o1.getuId().compareTo(o2.getuId());
            // 降序
            return o2.getuId().compareTo(o1.getuId());
        }
    }
    
    List<UserInfo> list = new ArrayList<UserInfo>();
    ...
    Collections.sort(list,new CustomComparator());
    

    条件排序:使用lambda表达式

    List<UserInfo> list = new ArrayList<UserInfo>();
    ...
    Collections.sort(list,(s1,s2)->(s1.getuId()-s2.getuId()));
    

    自定义排序(Comparable接口)

    package day3;
    
    public class UserInfo implements Comparable<UserInfo> {
    
        private Integer uId;
        private String uName;
    
        ...
    
        @Override
        public int compareTo(UserInfo o) {
            // 升序
            //return this.getuId() - o.getuId();
            
            // 降序
            return o.getuId() - this.getuId();
        }
    }
    
    List<UserInfo> list = new ArrayList<UserInfo>();
    ...
    Collections.sort(list);
    

    6. 泛型(Generics)

    泛型是JDK 1.5的一项新特性,它的本质是参数化类型的应用,也就是说所操作的数据类型被指定为一个参数,在用到的时候在指定具体的类型。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口和泛型方法。

    泛型的限制

    • 泛型的类型参数只能是类类型,不能是简单类型(简单类型的包装类可以)
    • 类型参数不能用于在方法中实例化其对象,如果需要实现这样的功能,可以使用反射
    • 使用泛型时,类型参数不允许为静态
    • 除非由无界通配符进行参数化,否则不允许转换为参数化类型
    • 泛型类不允许直接或间接扩展Throwable
    • 泛型不能使用数组
    • 泛型不能重载

    6.1 泛型类

    在类的申明时指定参数,即构成了泛型类。泛型类的类型参数部分可以有一个或多个类型参数,它们之间用逗号分隔。

    声明泛型类

    import java.util.List;
    
    public class Genit<T> {
        private List<T> list;
    
        public T Install(T entity) {
            list.add(entity);
            return null;
        }
    }
    

    何继承一个泛型类

    如果不传入具体的类型,则子类也需要指定类型参数,

    class Son<T> extends Test<T>{}
    

    如果传入具体参数,则子类不需要指定类型参数

    class Son extends Test<String>{}
    

    6.2 泛型方法

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

    • 定义泛型方法时,必须在返回值前边加一个<T>,来声明这是一个泛型方法

    定义泛型方法

    public class GenericM {
        public <T> void install(T c) {
            System.out.println(c.toString());
        }
    }
    

    调用泛型方法

    public class GenericMain {
        public static void main(String[] args) {
            GenericM h = new GenericM();
            h.install(1);
        }
    }
    

    6.3 泛型接口

    型接口与泛型类的定义基本一致

    定义泛型接口

    //定义一个泛型接口
    public interface BaseService<T> {
        T install(T entity);
        List<T> queryList();
    }
    

    实现泛型接口

    public class UserInfoService implements BaseService<UserInfo> {
        @Override
        public UserInfo install(UserInfo entity) {
            return null;
        }
    
        @Override
        public List<UserInfo> queryList() {
            return null;
        }
    }
    

    6.4 类型通配符

    泛型上限通配符

    通配符上界使用<? extends T>的格式,意思是需要一个T类型或者T类型的子类

    //只能传入number的子类或者number
    public void showKeyValue2(List<? extends Number> list) {  
        for (Number number : list) {  
            System.out.print(number.intValue()+" ");   
        }  
    }
    

    泛型下限通配符

    通配符下界使用<? super T>的格式,意思是需要一个T类型或者T类型的父类

    //只能传入Integer的父类或者Integer
    public void showKeyValue3(List<? super Integer> obj){
        System.out.println(obj);
    }
    

    无限定通配符

    无限定通配符使用<?>的格式,代表未知类型的泛型。 当可以使用Object类中提供的功能或当代码独立于类型参数来实现方法时,这样的参数可以使用任何对象

    public void showKeyValue1(List<?> list) {
        for (Object item : list) {  
            System.out.print(item + " ");   
        } 
    }
    

    <? extends T><? super T>的区别

    • <? extends T>表示该通配符所代表的类型是T类型的子类
    • <? super T>表示该通配符所代表的类型是T类型的父类

    7. 多线程(Thread)

    一个线程的生命周期

    创建线程

    Java 提供了三种创建线程的方法:

    • 通过实现 Runnable 接口
    • 通过继承 Thread 类本身
    • 通过 CallableFuture 创建线程

    主要概念

    • 线程同步
    • 线程间通信
    • 线程死锁
    • 线程控制:挂起、停止和恢复

    线程的优先级

    Java 线程的优先级是一个整数,其取值范围是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY ),

    默认情况下,每一个线程都会分配一个优先级 NORM_PRIORITY(5)

    7.1 Thread

    Thread是一个线程类,位于java.lang包下

    方法列表

    构造方法 描述
    new Thread() 创建一个线程对象
    new Thread(String name) 创建一个具有指定名称的线程对象
    new Thread(Runnable target) 创建一个基于Runnable接口实现类的线程对象
    new Thread(Runnable target ,String name) 创建一个基于Runnable接口实现类且有名称的线程对象
    实例方法 描述
    public void start() 使该线程开始执行;Java 虚拟机调用该线程的 run 方法
    public void run() 若线程是Runnable对象构造,则调用Runnable 对象 run 方法
    public final void setName(String name) 改变线程名称
    public final void setPriority(int priority) 更改线程的优先级
    public final void setDaemon(boolean on) 将该线程标记为守护线程或用户线程
    public final void join(long millisec) 待该线程终止的时间最长为 millis 毫秒
    public final void join(long millisec) 等待该线程终止的时间最长为 millis 毫秒
    public void interrupt() 中断线程
    public final boolean isAlive() 线程是否处于活动状态

    线程优先级

    class ContomRunable implements Runnable{
        @Override
        public void run() {
            System.out.println("start...");
        }
    }
    
    public class RannbleTesk {
        public static void main(String[] args) {
            ContomRunable cr = new ContomRunable();
            Thread td = new Thread(cr);	// 获取线程对象
            System.out.println(td.getPriority());	// 获取线程优先级
            td.setPriority(Thread.MAX_PRIORITY);	// 设置线程优先级
            System.out.println(td.getPriority());	// 获取线程优先级
        }
    }
    

    通过继承Thread类创建线程

    示例一:

    class ContomThead extends Thread{
       public void run() {
           System.out.println("start...");
       }
    }
    
    public class TreadDemo {
        public static void main(String[] args) {
            ContomThead ct = new ContomThead();
            ct.start(); 
        }
    }
    

    示例二:

    class ContomThead extends Thread {
        public ContomThead(String threadName) {
            super(threadName);
        }
    
        public void run() {
            System.out.println("start...");
        }
    }
    
    public class TreadDemo {
        public static void main(String[] args) {
            ContomThead ct = new ContomThead("线程一");
            ct.start();
        }
    }
    

    7.2 Runnable 接口

    创建线程,通过实现Runnable 接口

    class ContomRunable implements Runnable{
    
        @Override
        public void run() {
            System.out.println("start...");
        }
    }
    
    public class RannbleTesk {
    
        public static void main(String[] args) {
            ContomRunable cr = new ContomRunable();
            new Thread(cr).start();
        }
    }
    

    7.3 线程同步

    使用synchronized关键字实现线程同步

    方式一:同步方法,即synchronized关键字修饰的方法

    由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。也可以修饰静态方法,此时如果调用该静态方法,将会锁住整个类

    public class Bank {  
      
        private int count =0;//账户余额  
          
        //存钱  
        public  synchronized void addMoney(int money){  
            count +=money;  
            System.out.println(System.currentTimeMillis()+"存进:"+money);  
        }  
          
        //取钱  
        public  synchronized void subMoney(int money){  
            if(count-money < 0){  
                System.out.println("余额不足");  
                return;  
            }  
            count -=money;  
            System.out.println(+System.currentTimeMillis()+"取出:"+money);  
        }  
          
        //查询  
        public void lookMoney(){  
            System.out.println("账户余额:"+count);  
        }  
    } 
    

    方式二:同步代码块

    即有synchronized关键字修饰的语句块。被该关键字修饰的语句块会自动被加上内置锁,从而实现同步

    注:同步是一种高开销的操作,因此应该尽量减少同步的内容。通常没有必要同步整个方法,使用代码块同步关键代码即可

    public class Bank {
        private int count = 0;// 账户余额
    
        // 存钱
        public void addMoney(int money) {
            synchronized (this) {
                count += money;
            }
            System.out.println(System.currentTimeMillis() + "存进:" + money);
        }
    
        // 取钱
        public void subMoney(int money) {
            synchronized (this) {
                if (count - money < 0) {
                    System.out.println("余额不足");
                    return;
                }
                count -= money;
            }
            System.out.println(+System.currentTimeMillis() + "取出:" + money);
        }
        // 查询
        public void lookMoney() {
            System.out.println("账户余额:" + count);
        }
    }
    

    7.4 线程间通信

    7.5 线程死锁

    8. I/O 流

    8.1 File

    该类主要用于文件和目录的创建、文件的查找和文件的删除等,File对象代表磁盘中实际存在的文件和目录

    构造函数:创建FILE对象

    一:通过将给定路径名字符串转换成抽象路径名来创建

    File file = new File("E:\1.txt");
    

    二:根据父路径名字符串和子路径名字符串创建

    File file = new File("E:\","1.txt");
    

    三:通过给定的父抽象路径名和子路径名字符串创建

    File file1 = new File("E:\");
    File file = new File(file1,"1.txt");
    

    实例方法

    方法名称 描述
    公共操作
    String getName() 返回由此抽象路径名表示的文件或目录的名称
    boolean exists() 此抽象路径名表示的文件或目录是否存在
    boolean delete() 删除此抽象路径名表示的文件或目录(只能是空目录)
    String getParent() 返回此抽象路径名的父路径名的路径名字符串,若无,则返回 null
    File getParentFile() 返回此抽象路径名的父路径名的抽象路径名,若无,则返回 null
    String getPath() 此抽象路径名转换为一个路径名字符串
    boolean isAbsolute() 此抽象路径名是否为绝对路径名
    String getAbsolutePath() 返回抽象路径名的绝对路径名字符串
    目录操作
    boolean isDirectory() 此抽象路径名表示的文件是否是一个目录
    boolean mkdir() 创建此抽象路径名指定的目录(单个目录)
    boolean mkdirs() 创建此抽象路径名指定的目录,包括创建必需但不存在的父目录(多级目录)
    String[] list() 返回目录中的文件和目录的名称
    File[] listFiles() 返回目录中文件和目录的File类型实例
    文件操作
    boolean isFile() 此抽象路径名表示的文件是否是一个标准文件
    boolean createNewFile() 当文件不存在时创建文件,返回true,反之返回false
    boolean canRead() 应用程序是否可以读取此抽象路径名表示的文件
    boolean canWrite() 应用程序是否可以修改此抽象路径名表示的文件

    8.2 读写文件

    输入流用于从源读取数据,输出流用于向目标写数据

    8.3 字节输入流

    创建输入流对象

    使用字符串类型的文件名来创建一个输入流对象来读取文件:

    InputStream f = new FileInputStream("C:/java/hello");
    

    使用一个文件对象来创建一个输入流对象来读取文件:

    File f = new File("C:/java/hello");
    InputStream out = new FileInputStream(f);
    

    实例方法

    方法名称 描述
    void close() 闭此文件输入流并释放与此流有关的所有系统资源
    int read(int r) 读取指定字节的数据。返回为整数值。返回下一字节数据,如果已经到结尾则返回-1
    int read(byte[] r) 读取r.length长度的字节。返回读取的字节数。如果是文件结尾则返回-1

    8.4 字节输出流

    创建输出流对象

    如果该流在打开文件进行输出前,目标文件不存在,那么该流会创建该文件

    使用字符串类型的文件名来创建:

    OutputStream f = new FileOutputStream("C:/java/hello")
    

    使用一个文件对象来创建:

    File f = new File("C:/java/hello");
    OutputStream f = new FileOutputStream(f);
    

    实例方法

    方法名称 描述
    void close() 关闭此文件输入流并释放与此流有关的所有系统资源
    void write(int w) 把指定的字节写到输出流中
    void write(byte[] w) 把指定数组中w.length长度的字节写到OutputStream中

    8.5 字符输入流

    创建写入对象

    在给出 File 对象的情况下构造一个 FileWriter 对象:

    File file = new File("E:\2.txt");
    FileWriter fw = new FileWriter(file);	// 写入对象,重置
    FileWriter fw = new FileWriter(file,true);	// 写入对象,追加
    

    在给出文件名的情况下构造 FileWriter 对象:

    FileWriter fw = new FileWriter("E:\2.txt");	// 写入对象,重置
    FileWriter fw = new FileWriter("E:\2.txt",true);	// 写入对象,追加
    

    实例方法

    方法名称 描述
    void write(int c) 写入单个字符c
    void write(char [] c, int offset, int len) 写入字符数组中开始为offset长度为len的某一部分
    void write(String s, int offset, int len) 写入字符串中开始为offset长度为len的某一部分
    void flush() 刷新流
    void close() 关闭流

    8.6 字符输出流

    创建读取对象

    在给定从中读取数据的 File 的情况下创建:

    File file = new File("E:\2.txt");
    FileReader fr = new FileReader(file);
    

    在给定从中读取数据的文件名的情况下创建:

    FileReader fr = new FileReader("E:\2.txt");
    

    实例方法

    方法名称 描述
    int read() 读取单个字符,返回一个int型变量代表读取到的字符
    int read(char [] c, int offset, int len) 读取字符到c数组,返回读取到字符的个数
    void close() 关闭流

    9. 反/序列化

    10. Java 反射

    10.1 实现反射机制的类

    Java中反射机制的类都位于java.lang.reflect包中:

    • Class类:代表一个类

    • Constructor类:代表类的构造方法

    • Method类:代表类的方法

    • Field类:代表类的成员变量(成员变量也称为类的属性)

    10.2 Class 类型

    Class是JVM中代表“类和接口“的类,包含了某个特定类的结构信息

    方法列表

    方法名称 描述
    Class.forName() 静态方法,用户获取指定Class对象
    ClassObj.newInstance() 通过默认构造方法创建新的对象
    ClassObj.getConstructor() 获取指定的public修饰构造方法的Constructor对象
    ClassObj.getMethod() 获取指定的public修饰方法Method对象
    ClassObj.getField() 获取指定的public修饰成员变量Field对象
    ClassObj.getDeclaredFields() 获得类的所有属性(包括公共的,私有的)
    ClassObj.getFields() 获得类的public类型的属性
    ClassObj.getDeclaredMethods() 获得类的所有方法
    ClassObj.getMethods() 获得类的public类型的方法
    ClassObj.getConstrutors() 获得类的public类型的构造方法

    获取Class对象的三种方式

    通过Object类型对象获取:

    Object obj = new Customer();
    Class cls = obj.getClass();
    System.out.println(cls.getName());
    

    通过对象的“静态”的class属性:

    Class cls = Customer.class;
    System.out.println(cls.getName());
    

    通过Class类的静态方法:常用

    Class cus = Class.forName("com.Customer");
    System.out.println(cus.getName());
    

    注意:在运行期间,一个类,只有一个Class对象产生

    10.3 Constructor 类型

    方法列表

    方法名称 描述
    con.newInstance() 执行构造方法创建对象
    con.setAccessible(true) 暴力访问(忽略掉访问修饰符)

    获取构造方法

    获取所有的构造方法:

    Constructor[] conArray = ClassObj.getDeclaredConstructors();
    

    获取所有公有构造方法:

    Constructor[] conArray = ClassObj.getConstructors();
    

    获取公有、无参的构造方法:

    Constructor con = ClassObj.getConstructor(null);
    

    获取共有,有参的构造方法:

    Constructor con = ClassObj.getConstructor(new Class[]{String.class[,...]});
    

    获取私有,无参的构造方法:

    Constructor con = ClassObj.getDeclaredConstructor(null);
    

    获取私有,有参的构造方法:

    Constructor con = ClassObj.getDeclaredConstructor(new Class[]{String.class[,...]});
    

    调用构造方法

    调用共有,无参的构造方法:

    con.newInstance();	/	con.newInstance(null);
    

    调用共有,有参的构造方法:值的顺序,类型与构造方法一致

    con.newInstance(new Object[]{"李白",18[,...]});
    

    调用私有,无参的构造方法:

    con.setAccessible(true);
    con.newInstance();	/	con.newInstance(null);
    

    调用私有,有参的构造方法:

    con.setAccessible(true);
    con.newInstance(new Object[]{"李白",18[,...]});
    

    10.4 Method 类型

    方法名称 描述
    method.setAccessible(true) 暴力访问(忽略掉访问修饰符)

    获取方法

    获取所有的成员方法,包括私有的(不包括继承的):

    Method[] methodArray = ClassObj.getDeclaredMethods();
    

    获取所有公共方法,包含了父类的方法也包含Object类:

    Method[] methodArray = ClassObj.getMethods();
    

    获取指定公共方法,包括私有的:

    // 获取指定无参方法
    Method method = ClassObj.getMethod("Show");
    // 获取指定参数类型的方法
    Method method = ClassObj.getMethod("Show", String.class);
    

    获取指定公共方法:

    // 获取指定无参方法
    Method method = ClassObj.getMethod("Show");
    // 获取指定参数类型的方法
    Method method = ClassObj.getMethod("Show", String.class);
    

    调用方法

    Class ClassObj = Class.forName("com.Customer");
    Object obj = ClassObj.getConstructor().newInstance();
    

    调用公共,无参,无返回值方法:

    Method method = ClassObj.getMethod("Show");
    method.invoke(obj);
    

    调用公共,有参,无返回值方法方法:

    Method method = ClassObj.getMethod("Show",String.class);
    method.invoke(obj,"李白");
    

    调用公共,无参,有返回值方法方法:

    Method method = ClassObj.getMethod("GetInt");
    Object result = method.invoke(obj);
    System.out.println((Integer)result);
    

    调用私有,无参,无返回值方法:

    Method method = ClassObj.getDeclaredMethod("Show");
    method.setAccessible(true);
    method.invoke(obj);
    

    10.5 Field 类型

    方法名称 描述
    field.setAccessible(true) 暴力访问(忽略掉访问修饰符)

    获取字段

    获取所有字段,包括:私有、受保护、默认、公有:

    Field[] fields = ClassObj.getDeclaredFields();
    

    获取公共字段:

    Field[] fields = ClassObj.getFields();
    

    获取某个字段,不限:私有、受保护、默认、公有:

    Field field = ClassObj.getDeclaredField("id");
    

    获取某个公共字段:

    Field field = ClassObj.getField("id");
    

    设置字段值

    设置公共字段值:

    Class ClassObj = Class.forName("com.Customer");
    
    Field f = null;
    try {
        f = ClassObj.getField("name");
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }
    
    Object obj = ClassObj.getConstructor().newInstance();
    f.set(obj, "刘德华");
    
    Customer customer = (Customer) obj;
    System.out.println(customer.getName());
    

    设置私有字段值:

    Class ClassObj = Class.forName("com.Customer");
    
    Field f = null;
    try {
        f = ClassObj.getDeclaredField("name");
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }
    
    Object obj = ClassObj.getConstructor().newInstance();
    f.setAccessible(true);
    f.set(obj, "刘德华");
    
    Customer customer = (Customer) obj;
    System.out.println(customer.getName());
    

    11. 函数式接口

    11.1 常用函数

    name type description
    Consumer Consumer 接收T对象,不返回值
    Predicate Predicate 接收T对象并返回boolean
    Function Function<T,R> 接收T对象,返回R对象
    Supplier Supplier 提供T对象(例如工厂),不接收值

    11.2 Predicate

    package fun;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.function.Predicate;
    
    public class PredicateSmp {
        public static void main(String[] args) {
            List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
            Filter(list, n -> n > 3);
        }
    
        public static void Filter(List<Integer> list, Predicate<Integer> predicate) {
            for (Integer integer : list) {
                if (predicate.test(integer))
                    System.out.println(integer);
            }
        }
    }
    

    12. Java Stream

    12.1 简单介绍

    Stream流式处理是建立在Lambda基础上的多数据处理技术,可对集合进行迭代,去重,筛选,排序,聚合等

    package fun;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Optional;
    
    public class StreamSmp {
        public static void main(String[] args) {
            List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
            Optional<Integer> num = list.stream()
                .filter(x -> x % 2 == 0)
                .sorted((a, b) -> b - a)
                .findFirst();
            System.out.println(num.get());
        }
    }
    

    12.2 常用方法

    方法名称 描述
    forEach 循环遍历
    map 用于映射每个元素到对象的结果
    filter 用于通过设置的条件(Lambda表达式)过滤元素
    limit 用于获取指定数量的流
    sorted 用于对流进行排序
    distinct 用于对于进行去重
    Collectors 将流转换为集合和聚合操作

    示例一:mapToInt,filter,count

    package fun;
    
    import java.util.Arrays;
    import java.util.List;
    
    public class StreamSmp {
        public static void main(String[] args) {
            List<String> list = Arrays.asList("1", "2", "3", "4", "5");
            long sum = list.stream()
                    .mapToInt(i -> Integer.parseInt(i))
                    .filter(i -> i > 3)
                    .count();
            System.out.println(sum);
        }
    }
    

    示例二:map,collect

    package fun;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Locale;
    import java.util.stream.Collectors;
    
    public class PredicateSmp {
        public static void main(String[] args) {
            List<String> list = Arrays.asList("1", "2", "3", "4", "5");
            List newlist = list.stream()
                    .map(i->i.toLowerCase(Locale.ROOT))
                    .collect(Collectors.toList());
            System.out.println(newlist);
        }
    }
    

    12.3 创建Stream流

    基于数组创建

    Integer[] list = {1,2,3};
    Stream<Integer> stream = Stream.of(list);
    stream.forEach(e-> System.out.println(e));
    

    基于集合创建

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
    Stream<Integer> stream = list.stream();
    stream.forEach(e-> System.out.println(e));
    
    到达胜利之前无法回头!
  • 相关阅读:
    LINUX安装NGINX
    CentOS 设置mysql的远程访问
    centos6 mysql 安装与配置
    php读取用友u8采购入库单列表及详细
    php读取用友u8客户档案
    深度linux没有ll等命令的解决办法
    CentOS7下FTP的安装与配置
    虚拟机CentOS6.5搭建samba服务器实现文件共享
    linux 查找php.ini在那个文件夹
    CBE引擎概览
  • 原文地址:https://www.cnblogs.com/weiyongguang/p/14823585.html
Copyright © 2011-2022 走看看