# 常用类库
# 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();
}
}
}
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("程序退出!");
}
}
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");
}
}
2
3
4
5
6
7
8
9
10
# Cleaner类
Java中对象的整个生命周期大致分为下面几个阶段:
- Created:构建阶段,内存分配,构造对象,成员初始化。
- InUse:应用阶段,对象引用。
- Invisible:不可见阶段,超过对象使用范围。
- Unreachable:不可达阶段,对象不被引用。
- Collected:收集阶段,准备重新分配内存,调用finalize()方法。
- Finalized:终结阶段,finalize()执行完毕,内存空间等待回收。
- 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();
}
}
}
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();
}
}
}
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();
}
}
}
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();
}
}
}
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));
}
}
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+" ");
}
}
}
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的子类。它们的继承关系如下:
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);
}
}
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类完成。下面是它的类继承关系:
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();
}
}
}
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)"));
}
}
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+" ");
}
}
}
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);
}
}
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
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"));
}
}
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
2Person_zh_CN.properties: 中国区域访问资源
name={0}\u8C22{1} age=20
1
2Person_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,","!"));
}
}
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));
}
}
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());
}
}
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());
}
}
}
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();
}
}
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();
}
}
}
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类。它的类结构如下:
上面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);
}
}
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);
}
}
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);
}
}
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));
}
}
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));
}
}
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