# 常用类库

# AutoCloseable接口

从JDK 1.7时开始提供AutoCloseable接口,它可用来结合异常处理结构在资源操作完成后实现自动释放功能:

class TestAutoCloase implements AutoCloseable{

    public void Open() {
        System.out.println("类开始操作!");
    }

    public void NormalOper() {
        throw new RuntimeException("程序出现异常!");
    }

    @Override
    public void close() throws Exception {
        // TODO Auto-generated method stub
        System.out.println("自动处理销毁类逻辑");
    }

}

public class Main {
    public static void main(String[] args) {
        try(TestAutoCloase myClass = new TestAutoCloase()){
            myClass.Open();
            myClass.NormalOper();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# Runtime类

该类描述的是运行时状态,每一个JVM进程中都会提供唯一的一个Runtime类实例化对象,可通过Runtime类对象获取与JVM有关的运行时状态。Runtime类只存在一个实例化对象,在Runtime类中默认将其构造方法封装(单例设计模式),这样必须通过getRuntime()方法来获取实例化对象。

public class Main {
    public static void main(String[] args) {
        Runtime runtime = Runtime.getRuntime();
        System.out.println("可用处理器数量:"+runtime.availableProcessors());
        double tempNum;
        tempNum = runtime.maxMemory();
        System.out.println("最大可用内存:"+tempNum/1024/1024+"M");
        tempNum = runtime.totalMemory();
        System.out.println("可用内存:"+tempNum/1024/1024+"M");
        tempNum = runtime.freeMemory();
        System.out.println("空闲内存:"+tempNum/1024/1024+"M");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("程序退出!");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

注意:

  • maxMemory:返回java虚拟机能从操作系统中得到的最大内存,以字节为单位。比如java -Xmx512m ClassName获取的就是512m内存。
  • totalMemory:返回java已经从操作系统中得到的内存。如果没有添加-Xms参数,java是从操作系统逐渐获取的,用多少获取多少,直到达到maxMemory。
  • freeMemory:已从系统中获取,但实际运行并没有使用的内存。

下面是Java运行时参数:

  • -Xmx:设置java堆的最大值。
  • -Xms:设置java堆的初始值。
  • -Xss:设置java线程的栈大小。

# System类

该类是一个系统类,可输出系统的信息,比如用来获取程序运行时间:

public class Main {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        String string="";
        for(int i=0;i<3000;i++) {
            string+=i;
        }
        System.out.println((System.currentTimeMillis()-start)+" ms");
    }
}
1
2
3
4
5
6
7
8
9
10

# Cleaner类

Java中对象的整个生命周期大致分为下面几个阶段:

  1. Created:构建阶段,内存分配,构造对象,成员初始化。
  2. InUse:应用阶段,对象引用。
  3. Invisible:不可见阶段,超过对象使用范围。
  4. Unreachable:不可达阶段,对象不被引用。
  5. Collected:收集阶段,准备重新分配内存,调用finalize()方法。
  6. Finalized:终结阶段,finalize()执行完毕,内存空间等待回收。
  7. Free:释放阶段,对象空间回收。

在Object类中提供一个finalize()方法,主要是在对象被销毁前进行收尾操作,但是这样可能会影响JVM的对象分配与回收速度,从JDK 1.9开始提供了新的代替者——java.lang.ref.Cleaner类,此种方式会启动一个新的清理线程,并基于AutoClosable接口实现资源释放。

import java.lang.ref.Cleaner;

class MyCleaner implements Runnable,AutoCloseable{
    private static final Cleaner cleaner = Cleaner.create();
    private Cleaner.Cleanable cleanable;
    
    public MyCleaner() {
        // TODO Auto-generated constructor stub
        System.out.println("my cleaner is created!");
        this.cleanable = cleaner.register(this, this);
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("运行销毁逻辑!");
    }

    @Override
    public void close() throws Exception {
        // TODO Auto-generated method stub
        System.out.println("该类要被销毁!");
        this.cleanable.clean();
        
    }
    
}

public class Main {
    public static void main(String[] args) {
        try(MyCleaner mc1= new MyCleaner()){
            System.out.println("my cleaner 对象在运行!");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

# 克隆对象

假设有一个Java类,它有属性为引用类型,这个时候如果对ClassA进行拷贝,就涉及到浅拷贝和深拷贝:

  • 浅拷贝:拷贝时会拷贝对象的基本类型的属性,但是对于引用类型的属性不会复制,该类型的属性拷贝后的和原来的是同一个对象。
  • 深拷贝:拷贝对象的时除了拷贝基本类型的属性,也会拷贝引用类型的属性。

# 浅拷贝

class School implements Cloneable{
    String schoolName;
    Grade gradeLevel=new Grade("default grade");
    public School(String schoString,String gradeString,String classString) {
        SetInfo(schoString, gradeString, classString);
    }
    
    public void SetInfo(String schoString,String gradeString,String classString) {
        schoolName=schoString;
        gradeLevel.gradeName = gradeString;
        gradeLevel.classObj.className = classString;
    }
    

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }
    
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "school name:"+schoolName+";gradeLevel:"+gradeLevel.gradeName+";className:"+gradeLevel.classObj.className;
    }
}
class Grade{
    String gradeName;
    Class classObj = new Class("default class");
    public Grade(String name) {
        gradeName = name;
    }
}
class Class{
    String className;
    public Class(String name) {
        className = name;
    }
}

public class Main {
    public static void main(String[] args) {
        School school1 = new School("某某初中","初一","二班");
        try {
            School school2 = (School)school1.clone();
            school1.SetInfo("某高中","高一","三班");
            System.out.println("school1:"+school1+"\nschool2:"+school2);
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

# 深拷贝

从上面看出被拷贝后的对象gradeLevel同原来的对象一样。要想让拷贝后的对象引用属性同原来的不一样,需要深拷贝,需要重写clone方法或构造函数,重写的方式有:

  • 自己实现拷贝逻辑。
  • 引用属性实现Cloneable接口。

下面是通过重写clone方法,自己实现拷贝逻辑:

class School implements Cloneable{
    String schoolName;
    Grade gradeLevel=new Grade("default grade");
    public School(String schoString,String gradeString,String classString) {
        SetInfo(schoString, gradeString, classString);
    }
    
    public void SetInfo(String schoString,String gradeString,String classString) {
        schoolName=schoString;
        gradeLevel.gradeName = gradeString;
        gradeLevel.classObj.className = classString;
    }
    

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        School clonedObj = (School)super.clone();
        clonedObj.gradeLevel= new Grade(gradeLevel.gradeName);
        clonedObj.gradeLevel.classObj = new Class(gradeLevel.classObj.className);
        return clonedObj;
    }
    
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "school name:"+schoolName+";gradeLevel:"+gradeLevel.gradeName+";className:"+gradeLevel.classObj.className;
    }
}
class Grade{
    String gradeName;
    Class classObj = new Class("default class");
    public Grade(String name) {
        gradeName = name;
    }
}
class Class{
    String className;
    public Class(String name) {
        className = name;
    }
}

public class Main {
    public static void main(String[] args) {
        School school1 = new School("某某初中","初一","二班");
        try {
            School school2 = (School)school1.clone();
            school1.SetInfo("某高中","高一","三班");
            System.out.println("school1:"+school1+"\nschool2:"+school2);
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

下面是通过重写clone方法,引用属性实现Cloneable接口:

class School implements Cloneable{
    String schoolName;
    Grade gradeLevel=new Grade("default grade");
    public School(String schoString,String gradeString,String classString) {
        SetInfo(schoString, gradeString, classString);
    }
    
    public void SetInfo(String schoString,String gradeString,String classString) {
        schoolName=schoString;
        gradeLevel.gradeName = gradeString;
        gradeLevel.classObj.className = classString;
    }
    

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        School clonedObj = (School)super.clone();
        clonedObj.gradeLevel= (Grade)gradeLevel.clone();
        return clonedObj;
    }
    
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "school name:"+schoolName+";gradeLevel:"+gradeLevel.gradeName+";className:"+gradeLevel.classObj.className;
    }
}
class Grade implements Cloneable{
    String gradeName;
    Class classObj = new Class("default class");
    public Grade(String name) {
        gradeName = name;
    }
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        Grade clonedObj = (Grade)super.clone();
        clonedObj.classObj = (Class)classObj.clone();
        return clonedObj;
    }
}
class Class implements Cloneable{
    String className;
    public Class(String name) {
        className = name;
    }
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }
}

public class Main {
    public static void main(String[] args) {
        School school1 = new School("某某初中","初一","二班");
        try {
            School school2 = (School)school1.clone();
            school1.SetInfo("某高中","高一","三班");
            System.out.println("school1:"+school1+"\nschool2:"+school2);
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

# Math类

public class Main {
    public static void main(String[] args) {
        System.out.println(Math.abs(-19.35));
        System.out.println(Math.max(10, 20));
        System.out.println(Math.log(100));
        System.out.println(Math.round(15.8));
        System.out.println(Math.pow(10, 2));
    }
}
1
2
3
4
5
6
7
8
9

# Random随机数

该类主要是进行随机数的生成,下面是一个不重复生成随机数的例子:

import java.util.Random;

public class Main {
    public static void main(String[] args) {
        int[] repeatArr = GenerateRepeatArray(50, 100);
        PrintArr(repeatArr);
        int[] nonRepeatArr = GenerateNonRepeatArray(50, 100);
        PrintArr(nonRepeatArr);
    }
    
    public static int[] GenerateNonRepeatArray(int totalNum,int rangeMax) {
        int [] result = new int[totalNum];
        Random rand = new Random();
        for(int i=0;i<totalNum;) {
            int tempNum = rand.nextInt(rangeMax);
            System.out.println("正在生成第"+i+"个数!,生成数为;"+tempNum);
            if(!hasValue(result, tempNum)) {
                result[i++] = tempNum;
            }
        }
        return result;
    }
    
    public static boolean hasValue(int [] arr,int target) {
        for(int i : arr) {
            if(i==target) {
                return true;
            }
        }
        return false;
    }
    
    public static int[] GenerateRepeatArray(int totalNum,int rangeMax) {
        int [] result = new int[totalNum];
        Random rand = new Random();
        for(int i=0;i<totalNum;i++) {
            int tempNum = rand.nextInt(rangeMax);
            result[i] = tempNum;
        }
        return result;
    }
    
    public static void PrintArr(int [] arr) {
        System.out.println("----------------打印数组:");
        for(int i : arr) {
            System.out.println(i+" ");
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

# 大数字处理

当一个数很大的时候是无法使用基本类型接收的,早期使用String类接收,然后再拆分计算,为了解决大数计算,java.math提供了相关操作类,BigInteger和BigDecimal,它们都是Number的子类。它们的继承关系如下:

bigNumber

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;

public class Main {
    public static void main(String[] args) {
        BigInteger bigNum1 = new BigInteger("120000000000000");
        BigInteger bigNum2 = new BigInteger("100000");
        System.out.println("加法操作:"+bigNum1.add(bigNum2));
        System.out.println("减法操作:"+bigNum1.subtract(bigNum2));
        System.out.println("乘法操作:"+bigNum1.multiply(bigNum2));
        System.out.println("除法操作:"+bigNum1.divide(bigNum2));
        BigInteger result[] = bigNum1.divideAndRemainder(bigNum2);
        System.out.println("商:"+result[0]+",余数:"+result[1]);
        System.out.println(MyRound(new BigDecimal("12987600000000.8847362294723281"), 4));
    }
    
    public static BigDecimal MyRound(BigDecimal target,int scale) {
        return target.divide(new BigDecimal(1),scale,RoundingMode.HALF_UP);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# Date处理

该类用来处理日期相关的东西,他所保存的时间戳都是以毫秒为单位的。从JDK 1.8添加了LocalDateTime,更方便操作,比如时间的累加。使用java.util.Date可以获得当前的日期时间数据,但最终显示的数据不方便阅读,可以考虑对显示结果进行格式化处理操作,需要通过java.text.SimpleDateFormat类完成。下面是它的类继承关系:

dateClass

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;


public class Main {
    public static void main(String[] args) {
        Date myDate = new Date();
        System.out.println("当前时间为:"+myDate);

        long currentTimeStamp = myDate.getTime()+60*60*24*1000*2 ;
        System.out.println(new Date(currentTimeStamp));
        
        //JDK 1.8 之后添加了LocalDateTime
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println(localDateTime);
        System.out.println(localDateTime.plusDays(2));
        
        SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS");
        System.out.println(sDateFormat.format(myDate));
        Date parseDate;
        try {
            parseDate = sDateFormat.parse("2018-06-10 09:30:08.034");
            System.out.println(parseDate);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 正则表达式

从JDK 1.4之后,正则表达式(Regular Expression)已被默认支持,利用正则表达式可方便地实现数据的拆分,替换,验证。

常用正则标记为:

  • 单个字符:
    • \匹配""
    • \t匹配"\t"
    • \n匹配"\n"
  • 一组字符:
    • [abc]:匹配abc中的任意一个
    • [^abc]:不匹配abc中的任意一个
    • [a-zA-Z]:表示全部字符中的任意一个
    • [0-9]:匹配全部数字中的任意一个
  • 边界控制:
    • ^:正则表达式开始
    • $:正则表达式结束
  • 简写替代字符:
    • .:任意一位字符
    • \d:任意一位数字
    • \D:任意一位非数字字符
    • \w:任意一位字母,数字,_。
    • \W:任意一位非 字母,数字,_。
    • \s:任意一种空格控制字符,比如"\n","\t",空格。
    • \S:任意一种非空格字符。
  • 数量:
    • \?:前面模式出现0次或1次。
    • * : 前面模式出现0次或1次,或多次。
    • + :前面模式出现1次或多次。
    • {n}:正好出现n次。
    • {n,}:正好出现n次以上。
    • {n,m}:出现n到m次。
  • 逻辑表示:
    • 正则表达式1 正则表达式2:与
    • 正则表达式1 | 正则表达式2:或
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Main {
    public static void main(String[] args) {
        String numString="089";
        if(numString.matches("\\d+")) {
            System.out.println(Integer.parseInt(numString)*2);
        }
        
        //删除所有非字母和数字
        System.out.println("h*&e^%l$l#o,Y*o^u".replaceAll("[^a-zA-Z0-9]+", ""));
        
        //字符串拆分
        String str1="a9b3c2d9";
        for(String strT : str1.split("\\d+")) {
            System.out.print(strT+" ");
        }
        System.out.println();
        
        //将小数字符串转换为double
        String str2= "45.789";
        if(str2.matches("\\d+(\\.\\d+)?")) {
            System.out.println(Double.parseDouble(str2));
        }
        
        //将日期转换为Date
        String str3 = "1992-09-28";
        if(str3.matches("\\d{4}-\\d{2}-\\d{2}")) {
            try {
                Date myDate = (new SimpleDateFormat("yyyy-MM-dd")).parse(str3);
                System.out.println(myDate);
            } catch (ParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        //电话格式
//		String str4="(010)-56785567";
        String str4="010-56785567";
        String phoneRegex="((\\d{3,4}-)|(\\(\\d{3,4}\\)-))?\\d{7,8}";
        String phoneRegex2="((\\d{3,4})-)?\\d{7,8}";
        System.out.println(str4.matches(phoneRegex));
        
        //E-mail 格式
        String str5="test@163.com";
        System.out.println(str5.matches("[a-zA-Z0-9]\\w+@\\w+\\.(cn|com|com.cn|net|gov)"));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

# 正则包

从JDK 1.4之后开始提供java.util.regex,此包有两个核心的正则操作类:Pattern和Matcher。Pattern类负责正则表达式的编译以及Matcher类的获取。Matcher类则主要是执行验证,替换,查找匹配等操作。这个将一个正则表达式字符串编译成一个模式,然后用这个模式来对其他字符串匹配。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        String string="h&e&l#l(o";
        String regexString = "[^a-zA-Z]+";
        Pattern pattern1 = Pattern.compile(regexString);
        for(String strOne : pattern1.split(string)) {
            System.out.print(strOne+" ");
        }
        System.out.println();
        //字符串进行替换
        Matcher tempMatcher = pattern1.matcher(regexString);
        System.out.println(tempMatcher.replaceAll("."));
        
        //查看是否匹配
        Pattern pattern2 = Pattern.compile("\\d+");
        Matcher matcher = pattern2.matcher("909");
        System.out.println(matcher.matches());
        
        //选取其中一部分并进行替换
        String string2="insert into student(name,age) values(#{nameVal},#{ageVal})";
        String regexString2 = "#\\{\\w+\\}";
        Pattern pattern3 = Pattern.compile(regexString2);
        Matcher matcher2 = pattern3.matcher(string2);
        while(matcher2.find()) {
            //将# { }替换为空字符串
            String dataString = matcher2.group(0).replaceAll("#|\\{|\\}", "");
            System.out.println(dataString+" ");
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 国际化程序

如果一个程序需要在全世界各个国家运行,需要根据使用者所在区域来展现相应的语言文字,这就需要用到Java的本地化处理。

# Locale类

该类定义了不同国家的语言编码,除了根据当前系统自动获取实例化对象外,可以利用Locale类提供的一写常量来获取。

import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        Locale loc1 = new Locale("en","US");
        System.out.println(loc1);
        Locale loc2 = Locale.getDefault();
        System.out.println(loc2);
    }
}
1
2
3
4
5
6
7
8
9
10

# 配置资源文件

要在国际化之间运行的程序,文字是很重要的内容,可以把文字信息直接保存到资源文件中,这些文件后缀为.properties,资源文件中的所有数据均采用key=value形式定义,通过key来获取相应的value,属性文件可通过专门的Properties类进行操作,一个项目的资源文件一般有两类:

  • 公共资源文件:所有区域标记均可读到的内容,如Person.properties。
  • 具体区域的资源文件:该类文件名需在末尾追加语言和国家代码,比如Person_zh_CN.properties。

所有资源文件一定要定义在CLASSPATH中,允许资源文件保存在包中,包中的资源文件是包名.文件名,比如cn.my.package.Person.properties。

注意*.properties文件中所保存的内容均为字符串,必须进行编码才可以正确读取,在JDK 1.9以前的版本中会提供native2ascii.exe编码转换工具,从JDK 1.9开始支持UTF-8编码,此工具被取消,可直接存储中文。

# 读取资源文件

java.util.ResourceBundle类可读取资源文件,该类属于抽象类,可利用类中提供的static来获取实例化对象。在使用ResouceBundle类读取资源内容时,如果对应的key不存在,会出现MissingResourceException异常。

下面是一个读取案例,有一个名为Person.properties文件,其内容为:

name=xie
age=20
1
2

读取程序如下:

import java.util.Locale;
import java.util.ResourceBundle;

public class Main {
    public static void main(String[] args) {
        System.out.println(System.getProperty("user.dir"));
        Locale myLocale = new Locale("en","US");
        ResourceBundle resouceBundle = ResourceBundle.getBundle("Person");
        System.out.println("name:"+resouceBundle.getString("name"));
        System.out.println("age:"+resouceBundle.getString("age"));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

一个资源文件要在Eclipse中识别需要:

  • 该资源文件导入到Eclipse中。
  • 该资源文件所在目录添加到了项目属性->JavaBuildPath->Source中。

# 案例

该案例关键在于根据用户所在区域不同显示不同语言的文字,一般会有一个公共的资源文件,同时根据不同的区域环境动态加载对应资源信息,需要有3个资源文件:

  • Person.properties:公共资源,各个区域都能访问

    name={0}\u8C22(xie){1}
    age=20
    
    1
    2
  • Person_zh_CN.properties: 中国区域访问资源

    name={0}\u8C22{1}
    age=20
    
    1
    2
  • Person_en_US.properties:英国区域访问资源

    name={0}xie{1}
    age=20
    
    1
    2

上面{编号}是占位符,可通过MessageFormat进行格式化参数输出。

import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;

public class Main {
    public static void main(String[] args) {
        System.out.println(Locale.getDefault());
        Locale myLocale1 = new Locale("en","US");
        Locale myLocale2 = new Locale("zh","CN");
        ResourceBundle resouceBundle = ResourceBundle.getBundle("Person",myLocale1);
        System.out.println("name:"+MessageFormat.format(resouceBundle.getString("name"),"hello,","?"));
        System.out.println("age:"+MessageFormat.format(resouceBundle.getString("age"),"greet,","!"));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# Arrays数组操作类

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int dataA[]= new int[] {1,2,3};
        int dataB[]= new int[] {1,2,3};
        int dataC[]= new int[] {1,2,4};
        System.out.println(Arrays.compare(dataA, dataB));
        System.out.println(Arrays.compare(dataC, dataA));
        System.out.println(Arrays.equals(dataA, dataB));
        Arrays.fill(dataC, 1);
        System.out.println(Arrays.toString(dataC));
        
        int dataD[]= new int[] {
                1,56,23,45,13,86,32,34,56
        };
        Arrays.sort(dataD);;
        System.out.println(Arrays.toString(dataD));
        System.out.println(Arrays.binarySearch(dataD, 32));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# UUID无重复数据

UUID(Universally Unique Identifier,通用唯一识别码)是一种基于时间戳,时钟序列,硬件识别号等随机生成的唯一编码的技术。

import java.util.UUID;

public class Main {
    public static void main(String[] args) {
        UUID uid = UUID.randomUUID();
        System.out.println(uid.toString());
    }
}
1
2
3
4
5
6
7
8

# Optional空处理

程序开发中经常会出现由于null带来的NullPointerException异常,从JDK 1.8开始引入了java.util.Optional类,此类可实现null类型的提前判断和处理,合理地使用此类可减少项目中NullPointerException异常出现。

import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        String str1 = null;
        String str2 = "hello";
        Optional<String> strOptional = Optional.ofNullable(str1);
        if(strOptional.isPresent()) {
            System.out.println(strOptional.get());
        }
        Optional<String> strOptional2 = Optional.of(str2);
        if(strOptional2.isPresent()) {
            System.out.println(strOptional2.get());
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

下面来应用在一个要求返回值必须为非null的场景中

import java.util.Optional;

class MyMessageReceiver{
    Optional<IMessage> opt;
    public Optional<IMessage> getMessage(){
        opt = Optional.of(new MyMessage());
        return opt;
    }
    
    public void useMessage() {
        if(opt.isPresent()) {
            System.out.println(opt.get().getInfo());
        }
    }
}

interface IMessage {
    public String getInfo();
}

class MyMessage implements IMessage{

    @Override
    public String getInfo() {
        // TODO Auto-generated method stub
        return "hello wolrd";
    }	
}

public class Main {
    public static void main(String[] args) {
        MyMessageReceiver messageReceiver = new MyMessageReceiver();
        messageReceiver.getMessage();
        messageReceiver.useMessage();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# ThreadLocal

在多线程并发执行中,为了能访问每个线程中的成员,可通过java.lang.ThreadLocal类实现数据的保存与获取,它主要进行数据的保存,获取与删除,由于ThreadLocal类是在多线程并发访问时使用,所以它其中保存的数据除了用户所需的数据外,还会保存当前的线程对象,在获取数据时通过当前线程对象来获取。可以把ThreadLocal想象成一个大的储物柜,每一个操作储物柜的客户是一个线程,每个线程只允许操作自己的储物柜,这就保证了存储物品的安全。

class Info{
    String infoString;
}

class ThreadChannel{
    private static final ThreadLocal<Info> THREAD_LOCAL = new ThreadLocal<Info>();
    public static void setInfo(Info info) {
        THREAD_LOCAL.set(info);
    }
    
    public static void Send() {
        System.out.println(Thread.currentThread().getName()+" 发送消息:"+THREAD_LOCAL.get().infoString);
    }
}

public class Main {
    public static void main(String[] args) {
        for(int i=0;i<3;i++) {
            final int tempI=i;
            new Thread(()->{
                Info info = new Info();
                info.infoString="线程 "+tempI+"的信息";
                ThreadChannel.setInfo(info);
                ThreadChannel.Send();
            },"线程_"+i+":").start();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 定时调度

定时调度是指可以根据既定的时间安排实现程序任务的自动执行,在Java中所有定时调度的任务都通过一个单独的线程进行管理,每一个调度任务类都需要继承java.util.TimerTask父类,任务的启动也需通过java.util.Timer类。它的类结构如下:

timerTask

上面schedule()与scheduleAtFixedRate()的区别在于重复执行任务时:

  • schedule()执行时间间隔永远是固定的。
  • scheduleAtFixedRate()方法可以根据出现的延迟时间自动调整下一次间隔的执行时间。
import java.util.Timer;
import java.util.TimerTask;

class MyTask extends TimerTask{
    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println(Thread.currentThread().getName()+" 执行定时任务,当前时间为:"+System.currentTimeMillis());
    }
}
public class Main {
    public static void main(String[] args) {
        Timer timer= new Timer();
        //timer.scheduleAtFixedRate(new MyTask(), 100, 1000);
        timer.schedule(new MyTask(),100, 1000);

    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# Base64加密与解密

Base64是直接利用64个可打印字符来表示二进制数据的算法,是在网络传输中较为常见的一种加密算法,从JDK 1.8开始提供java.util.Base64的工具类,同时提供了两个Base64内部类来实现数据加密与解密操作。

import java.util.Base64;

public class Main {
    public static void main(String[] args) {
        String infoString = "hello world!";
        //数据加密
        String encodeString = new String(Base64.getEncoder().encode(infoString.getBytes()));
        System.out.println(encodeString);
        //数据解密
        String decodeString = new String(Base64.getDecoder().decode(encodeString));
        System.out.println(decodeString);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

Base64属于JDK的原始实现,单纯的加密并不安全,为了获取更加安全的加密操作,可以利用盐值,自定义格式,以及多次加密来保证项目中的数据安全。

import java.util.Base64;

class MyEncodeMethod{
    private static final String SALT_STRING="hello";
    private static int REPEAT_NUM=5;
    public static String encode(String str) {
        String tempString = str+"{"+SALT_STRING+"}";
        byte data[] = tempString.getBytes();
        for(int i=0;i<REPEAT_NUM;i++) {
            data = Base64.getEncoder().encode(data);
        }
        return new String(data);
    }
    
    public static String decode(String str) {
        byte data[] = str.getBytes(); 
        for(int i=0;i<REPEAT_NUM;i++) {
            data = Base64.getDecoder().decode(data);
        }
        return new String(data).replaceAll("\\{\\w+\\}", "");
    }
}
public class Main {
    public static void main(String[] args) {
        String encodeString = MyEncodeMethod.encode("hello world");
        System.out.println("encode string:"+encodeString);
        String decodeString = MyEncodeMethod.decode(encodeString);
        System.out.println(decodeString);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 比较器

数组中进行排序,基本数据类型都能直接确定大小关系,但是引用数据类型的大小比较需要自定义比较器,有Comparable和Comparator。

# Comparable

该类是从JDK 1.2开始提供的,它是用于排序的标准接口,Java在进行对象数组排序时会利用此接口中的方法进行大小关系比较,来确定两个对象之间的大小。

import java.util.Arrays;

class Person implements Comparable<Person>{
    String name;
    int worktime;
    int score;
    
    public Person(String n,int w,int s) {
        // TODO Auto-generated constructor stub
        this.name=n;
        this.score=w;
        this.worktime=s;
    }

    @Override
    public int compareTo(Person o) {
        // TODO Auto-generated method stub
        if(this.score>o.score) {
            return -1;
        }

        if(this.score<o.score) {
            return 1;
        }
        
        if(this.score == o.score) {
            if(this.worktime >= o.worktime) {
                return -1;
            }else {
                return 1;
            }
        }
        
        return 100;
    }
    
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "name:"+name+",worktime:"+worktime+",score:"+score;
    }
    
}
public class Main {
    public static void main(String[] args) {
        Person personData[] = new Person[] {
                new Person("xie", 80, 2),
                new Person("li", 70, 3),
                new Person("wang", 80, 3),
                new Person("zhang", 90, 4),
        };
        
        Arrays.sort(personData);
        System.out.println(Arrays.toString(personData));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

# Comparator

除了在类内实现Comparable接口,还可以使用java.util.Comparator:

import java.util.Arrays;
import java.util.Comparator;

class PersonComparator implements Comparator<Person>{

    @Override
    public int compare(Person o1, Person o2) {
        // TODO Auto-generated method stub
        if(o1.score>o2.score) {
            return -1;
        }

        if(o1.score<o2.score) {
            return 1;
        }
        
        if(o1.score == o2.score) {
            if(o1.worktime >= o2.worktime) {
                return -1;
            }else {
                return 1;
            }
        }
        return 100;
    }
    
}

class Person {
    String name;
    int worktime;
    int score;
    
    public Person(String n,int w,int s) {
        // TODO Auto-generated constructor stub
        this.name=n;
        this.score=w;
        this.worktime=s;
    }

    
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "name:"+name+",worktime:"+worktime+",score:"+score;
    }
    
}
public class Main {
    public static void main(String[] args) {
        Person personData[] = new Person[] {
                new Person("xie", 80, 2),
                new Person("li", 70, 3),
                new Person("wang", 80, 3),
                new Person("zhang", 90, 4),
        };
        
        Arrays.sort(personData,new PersonComparator());
        System.out.println(Arrays.toString(personData));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61