一、UUID
一種生成無重複字符串的的程序類,這種程序類主要是根據時間戳實現一個自動的無重複的的字符串。一般在獲取UUID的時候都是隨機產生的一個內容,所以很少用到構造方法。通常用以下幾種方式來獲取.
獲取UUID對象:public static UUID randomUUID();
根據字符串獲取UUID內容:public static UUID fromString(String name);
二、Optional
主要功能是進行null的處理,以前的處理方式是增加是否爲空的驗證。這是一種被動驗證操作。
範例:以前處理的方式
public class Test1 { public static void main(String[] args) { MessageUtil.useMessage(null); } } interface IMessage{ public String getContent(); } class MessageImpl implements IMessage{ @Override public String getContent() { return null; } } class MessageUtil{ public MessageUtil(){ } public static IMessage getMessage(){ return new MessageImpl(); } public static void useMessage(IMessage msg){ if(msg != null) { System.out.println(msg.getContent()); //msg可能爲空 } } }
現在提供了一個Optional類來處理null的情況,這個類提供瞭如下幾種方法:
1.返回空數據:public static<T> Optional<T> empty()
2.獲取數據: public T get()
3.保存數據,但是不允許出現null:public static <T> Optional<T> of(T value)
如果在保存數據時爲空,將拋出NullPointerException異常;
4.保存數據,允許爲空:public static <T> Optional<T> ofNullable(T value);
5.空的時候返回其他數據:public T orElse(T other);
範例:修改程序,按正常的結構
public class Test1 { public static void main(String[] args) { IMessage temp = MessageUtil.getMessage().get(); MessageUtil.useMessage(temp); } } interface IMessage{ public String getContent(); } class MessageImpl implements IMessage{ @Override public String getContent() { return "www.baidu.com"; } } class MessageUtil{ public MessageUtil(){ } public static Optional<IMessage> getMessage(){ return Optional.of(new MessageImpl()); } public static void useMessage(IMessage msg){ if(msg != null) { System.out.println(msg.getContent()); //msg可能爲空 } } }
如果說現在數據保存的內容是null,則我們就會在保存處報異常。
public class Test1 { public static void main(String[] args) { IMessage temp = MessageUtil.getMessage().get(); MessageUtil.useMessage(temp); } } interface IMessage{ public String getContent(); } class MessageImpl implements IMessage{ @Override public String getContent() { return "www.baidu.com"; } } class MessageUtil{ public MessageUtil(){ } public static Optional<IMessage> getMessage(){ return Optional.of(null); } public static void useMessage(IMessage msg){ if(msg != null) { System.out.println(msg.getContent()); //msg可能爲空 } } }
Exception in thread "main" java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at java.util.Optional.<init>(Optional.java:96)
at java.util.Optional.of(Optional.java:108)
at MessageUtil.getMessage(Test1.java:31)
at Test1.main(Test1.java:9)
由於Optional類中允許保存有null的內容ofNullable,所以在數據獲取的時候可以進行null的處理,但是如果爲空,在get()數據時就會出現以下異常:
Exception in thread "main" java.util.NoSuchElementException: No value present
at java.util.Optional.get(Optional.java:135)
at Test1.main(Test1.java:9)
範例:orElse
public class Test1 { public static void main(String[] args) { IMessage temp = MessageUtil.getMessage().orElse(new MessageImpl()); MessageUtil.useMessage(temp); } } interface IMessage{ public String getContent(); } class MessageImpl implements IMessage{ @Override public String getContent() { return "www.baidu.com"; } } class MessageUtil{ public MessageUtil(){ } public static Optional<IMessage> getMessage(){ return Optional.ofNullable(null); } public static void useMessage(IMessage msg){ if(msg != null) { System.out.println(msg.getContent()); //msg可能爲空 } } }
public class Test1 { public static void main(String[] args) { IMessage temp = MessageUtil.getMessage().orElse(null); MessageUtil.useMessage(temp); } } interface IMessage{ public String getContent(); } class MessageImpl implements IMessage{ @Override public String getContent() { return "www.baidu.com"; } } class MessageUtil{ public MessageUtil(){ } public static Optional<IMessage> getMessage(){ return Optional.ofNullable(new MessageImpl()); } public static void useMessage(IMessage msg){ if(msg != null) { System.out.println(msg.getContent()); //msg可能爲空 } } }
orElse 如果爲空,則用orElse()括號裏面的內容,不爲空則會使用傳過來的對象。
三、ThreadLocal
範例:消息發送結構
/*測試類*/ public class Test1 { public static void main(String[] args) { Message msg = new Message(); msg.setMsg("666"); Channel.setMessage(msg); Channel.send(); } } /*消息類*/ class Message{ private String msg; public void setMsg(String msg){ this.msg = msg; } public String getMsg(){ return msg; } } /*消息發送通道類*/ class Channel{ private static Message message; public Channel(){ //私有化 } public static void setMessage(Message msg){ message = msg; } public static void send(){ System.out.println(Thread.currentThread().getName()+"發送了"+message.getMsg()); } }
這是傳統的使用單線程實現了消息發送的實例,如果採用多個線程實現呢?結果如下:
範例:多線程實現消息發送
/*測試類*/ public class Test1 { public static void main(String[] args) throws Exception{ new Thread(()->{ Message msg = new Message(); msg.setMsg("線程消息A"); Channel.setMessage(msg); Channel.send(); },"消息線程A").start(); new Thread(()->{ Message msg = new Message(); msg.setMsg("線程消息B"); Channel.setMessage(msg); Channel.send(); },"消息線程B").start(); new Thread(()->{ Message msg = new Message(); msg.setMsg("線程消息C"); Channel.setMessage(msg); Channel.send(); },"消息線程C").start(); } } /*消息類*/ class Message{ private String msg; public void setMsg(String msg){ this.msg = msg; } public String getMsg(){ return msg; } } /*消息發送通道類*/ class Channel{ private static Message message; public Channel(){ //私有化 } public static void setMessage(Message msg){ message = msg; } public static void send(){ System.out.println(Thread.currentThread().getName()+"發送了"+message.getMsg()); } }
出現了以下結果:
分析結果,並沒有做到哪個線程發該線程自己的消息,原因是通道類用Message對象來設置消息,存在當線程A設置消息對象的時候,線程B也開始設置消息對象,消息便被覆蓋了,所以造成了這個原因。具體結構圖如下:
要解決這個問題的思想是:每個線程對象存到屬於它自己的地方,取數據的時候也是一樣。所以用到了ThreadLocal類
ThreadLocal類中包括了以下方法:
設置數據:public void set(T value);
獲取數據:public T get()
刪除數據:public void remove()
範例:ThreadLocal類的使用,解決線程同步問題
/*測試類*/ public class Test1 { public static void main(String[] args) throws Exception{ new Thread(()->{ Message msg = new Message(); msg.setMsg("線程消息A"); Channel.setMessage(msg); Channel.send(); },"消息線程A").start(); new Thread(()->{ Message msg = new Message(); msg.setMsg("線程消息B"); Channel.setMessage(msg); Channel.send(); },"消息線程B").start(); new Thread(()->{ Message msg = new Message(); msg.setMsg("線程消息C"); Channel.setMessage(msg); Channel.send(); },"消息線程C").start(); } } /*消息類*/ class Message{ private String msg; public void setMsg(String msg){ this.msg = msg; } public String getMsg(){ return msg; } } /*消息發送通道類*/ class Channel{ private final static ThreadLocal<Message> THREAD_LOCAL = new ThreadLocal<>(); public Channel(){ //私有化 } public static void setMessage(Message msg){ THREAD_LOCAL.set(msg); } public static void send(){ System.out.println(Thread.currentThread().getName()+"發送了"+THREAD_LOCAL.get().getMsg()); } }
運行結果:
具體結構:
每一個線程通過ThreadLocal只允許保存一個數據。
四、定時調度
TimerTask實現了Runnable接口的類:public abstract class TimerTask extends Object implements Runnable
範例:實現定時任務
class MyTask extends TimerTask{ @Override public void run(){ System.out.println("啓動"+System.currentTimeMillis());//獲取當前時間返回類型爲long } } public class TimerDemo { public static void main(String[] args) { Timer timer = new Timer(); MyTask task = new MyTask(); timer.scheduleAtFixedRate(task,1000,1000);//第一個1000代表延遲,第二個1000代表間隔 } }
五、Base64加密與解密
class StringUtil{ private static final String SALT="666"; private static final int REPEAT = 5; public static String encode(String str){ String temp = str+"{"+SALT+"}"; byte[] bytes = temp.getBytes(); for (int i = 0; i< REPEAT ; i++){ bytes = Base64.getEncoder().encode(bytes); } return new String(bytes); } public static String decode(String str){ byte[] bytes = str.getBytes(); for (int i = 0; i < REPEAT ; i++){ bytes = Base64.getDecoder().decode(bytes); } return new String(bytes).replaceAll("\\{\\w+\\}",""); } } public class Base64Demo { public static void main(String[] args) { String str ="今天天氣很好,非常好"; System.out.println(StringUtil.decode(StringUtil.encode(str))); } }