一、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))); } }