开发支持类库
1、UUID类
UUID是一种生成无重复字符串的一种程序类,这种程序类的主要功能是根据时间戳实现一个自动的无重复的字符串定义
一般获取UUID的时候往往都是随机生成一个内容,所以可以通过如下方式获取
- 获取UUID对象:public static UUID randomUUID()
- 根据UUID获取字符串内容:public static UUID fromString (String name)
public class JavaAPIDemo {
public static void main(String[] args) throws ParseException {
UUID uuid = UUID.randomUUID();
System.out.println(uuid.toString());
}
}
在对一些文件进行自动命名处理的情况下,UUID类型非常好用
2、Optional类
Optional类的主要功能是进行null的相关处理,在以前进行程序开发的时候,如果为了防止程序之中出现空指向异常,往往追加bull的验证
范例:传统的引用传递问题
interface IMessage {
String getContent();
}
class MessageImpl implements IMessage{
@Override
public String getContent() {
return "";
}
}
class MessageUtil{
private MessageUtil(){}
public static IMessage getMessage(){
return null;
}
public static void useMessage(IMessage message){
System.out.println(message.getContent()); //有可能出现空导致null指向异常
}
}
public class JavaAPIDemo {
public static void main(String[] args) throws ParseException {
MessageUtil.useMessage(MessageUtil.getMessage());
}
}
在引用接受的以防往往都是被动的进行判断,所以为了解决这种被动的处理操作,在Java类中提供有一个Optional的类,这个类可以实现null的处理,提供有如下方法:
- 返回空数据:public static Optionalempty()
- 获取数据:public T get()
- 保存数据,但是不允许出现null:public static Optional of(T value)
- 如果在保存数据的时候纯在有null,则会抛出NullPointerException异常
- 保存数据,允许为空:public static Option ofNullable(T value)
- 空的时候返回其他数据:public T orElse(T other)
范例:修改程序,按照正规结构完成
interface IMessage {
String getContent();
}
class MessageImpl implements IMessage{
@Override
public String getContent() {
return "";
}
}
class MessageUtil{
private MessageUtil(){}
public static Optional<IMessage> getMessage(){
return Optional.of(new MessageImpl()); //有对象
}
public static void useMessage(IMessage message){
System.out.println(message.getContent()); //有可能出现空导致null指向异常
}
}
public class JavaAPIDemo {
public static void main(String[] args) throws ParseException {
IMessage message = MessageUtil.getMessage().get();
MessageUtil.useMessage(message);
}
}
如果说现在的数据内容是null,则就会在保存处出现异常
由于Optional类中允许保存有null的内容,所以在数据获取的时候也可以进行null的处理,但是如果为null,则在使用get()获取数据的时候就会出现异常,所以可以更换为orElse()方法
interface IMessage {
String getContent();
}
class MessageImpl implements IMessage{
@Override
public String getContent() {
return "linlin";
}
}
class MessageUtil{
private MessageUtil(){}
public static Optional<IMessage> getMessage(){
return Optional.ofNullable(null); //有对象
}
public static void useMessage(IMessage message){
System.out.println(message.getContent()); //有可能出现空导致null指向异常
}
}
public class JavaAPIDemo {
public static void main(String[] args) throws ParseException {
IMessage message = MessageUtil.getMessage().orElse(new MessageImpl());
MessageUtil.useMessage(message);
}
}
在所有引用数据类型的操作处理之中,null是一个重要的技术问题,所以Optional类对于处理null很有帮助,也是进行项目开发之中使用次数比较多的一种程序类
3、ThreadLocal类
在真正去了解ThreadLocal类作用的时候,编写一个简单的程序去做一个先前分析
class Message{ //消息发送的消息体
private String info;
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
class Channel{ //消息发送通道
private static Message message;
public Channel(){}
public static void setMessage(Message msg) {
message = msg;
}
public static void send(){ //消息的发送
System.out.println("消息发送:" + message.getInfo());
}
}
public class JavaAPIDemo {
public static void main(String[] args) throws ParseException {
Message message = new Message(); //实例化消息主体对象
message.setInfo("linlin");
Channel.setMessage(message);
Channel.send();
}
}
对于当前的程序类实际上采用的是一种单线程的模式来进行的。那么如果在多线程的状态下能否实现完全一致的操作效果呢
范例:多线程的影响(启动三个线程)
class Message{ //消息发送的消息体
private String info;
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
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.getInfo());
}
}
public class JavaAPIDemo {
public static void main(String[] args) throws ParseException {
new Thread(() -> {
Message message = new Message(); //实例化消息主体对象
message.setInfo("第一个线程信息"); //设置发送内容
Channel.setMessage(message); //设置要发送的信息
Channel.send(); //发送消息
} , "消息发送者A").start();
new Thread(() -> {
Message message = new Message(); //实例化消息主体对象
message.setInfo("第二个线程信息"); //设置发送内容
Channel.setMessage(message); //设置要发送的信息
Channel.send(); //发送消息
} , "消息发送者B").start();
new Thread(() -> {
Message message = new Message(); //实例化消息主体对象
message.setInfo("第三 个线程信息"); //设置发送内容
Channel.setMessage(message); //设置要发送的信息
Channel.send(); //发送消息
} , "消息发送者C").start();
}
}
/*
结果:
消息发送者A消息发送:第三 个线程信息
消息发送者B消息发送:第三 个线程信息
消息发送者B消息发送:第三 个线程信息
*/
这个时候消息的发送产生了影响
在Channel(所有发送的消息通道)核心结构不改变的情况下,需要考虑到每个线程的独立操作问题。那么在这样的情况下,对于Channel类而言除了要保留有发送的消息之外,还应该多存放有一个每一个线程的标记(当前线程),那么这个时候就可以通过ThreadLocal类来存放数据。在ThreadLocal类里面提供有如下方法:
- 构造方法:pubic ThreadLocal()
- 设置数据:public void set(T value)
- 取出数据:public T get()
- 删除数据:public void remove()
class Message{ //消息发送的消息体
private String info;
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
class Channel{ //消息发送通道
private static final ThreadLocal<Message> THREADLOCAL = new ThreadLocal<Message>();
public Channel(){}
public static void setMessage(Message msg) {
THREADLOCAL.set(msg);
}
public static void send(){ //消息的发送
System.out.println(Thread.currentThread().getName() + "消息发送:" + THREADLOCAL.get().getInfo());
}
}
public class JavaAPIDemo {
public static void main(String[] args) throws ParseException {
new Thread(() -> {
Message message = new Message(); //实例化消息主体对象
message.setInfo("第一个线程信息"); //设置发送内容
Channel.setMessage(message); //设置要发送的信息
Channel.send(); //发送消息
} , "消息发送者A").start();
new Thread(() -> {
Message message = new Message(); //实例化消息主体对象
message.setInfo("第二个线程信息"); //设置发送内容
Channel.setMessage(message); //设置要发送的信息
Channel.send(); //发送消息
} , "消息发送者B").start();
new Thread(() -> {
Message message = new Message(); //实例化消息主体对象
message.setInfo("第三个线程信息"); //设置发送内容
Channel.setMessage(message); //设置要发送的信息
Channel.send(); //发送消息
} , "消息发送者C").start();
}
}
/*
结果:
消息发送者A消息发送:第一个线程信息
消息发送者C消息发送:第三个线程信息
消息发送者B消息发送:第二个线程信息
*/
每一个线程通过ThreadLocal只允许保存一个数据
4、定时调度
定时器的主要操作是进行定时任务的处理,这种任务的处理只是实现了一种间隔触发的操作
如果要实现处理操作主要需要有一个定时操作的主体类,以及一个定时任务的控制
可以使用两个类实现:
-
java.util.TimerTask类:实现定时任务处理
-
java.util.Timer:进行任务的启动,启动的方法
- 任务启动:public void schedule(TimeTask task , long delay)延迟单位为毫秒
- 间隔触发:public void scheduleAtFixedRate(TimerTask task , long delay , long period)
范例:实现定时任务处理
class MyTask extends TimerTask{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "、定时任务执行,当前时间:" + System.currentTimeMillis());
}
}
public class JavaAPIDemo {
public static void main(String[] args) throws ParseException {
Timer timer = new Timer();//定时任务
//定义间隔任务,100毫秒后开始执行,每1秒执行一次
timer.scheduleAtFixedRate(new MyTask() , 100 , 1000);
}
}
这种定时是由JDK最原始的方式提供的支持,但是实际上开发之中利用此类方法进行的定时处理实现的代码会非常的复杂
5、Base64加密与解密
正常来讲加密基本上永远都要伴随着解密,所谓的加密或者是解密往往都需要有一些所谓的规则。从JDK1.8开始提供有一种新的加密处理操作类,Base64 ,在这个类里面有两个内部类:
- Base64.Encoder:进行加密处理:
- 加密处理:public byte[] encode(byte[] src)
- Base64.Decoder:进行解密处理
- 解密处理:public byte[] decode(String src)
范例:实现加密与解密操作
public class JavaAPIDemo {
public static void main(String[] args) throws ParseException {
String msg = "linlin";
String encMsg = new String(Base64.getEncoder().encode(msg.getBytes()));
System.out.println(encMsg);
String oldMsg = new String(Base64.getDecoder().decode(encMsg));
System.out.println(oldMsg);
}
}
虽然Base64可以实现加密与解密的处理,但是由于是一个公版的算法,所以如果直接对数据进行加密往往并不安全,那么最好的做法是使用盐值操作
public class JavaAPIDemo {
public static void main(String[] args) throws ParseException {
String salt = "java";
String msg = "linlin" + "{" + salt + "}";
String encMsg = new String(Base64.getEncoder().encode(msg.getBytes()));
System.out.println(encMsg);
String oldMsg = new String(Base64.getDecoder().decode(encMsg));
System.out.println(oldMsg);
}
}
即便现在有盐值,实际上发现加密的效果也不是很好,最好的做法是多次加密
范例:复杂加密
class StringUtil{
private static final String SALT = "java"; //公共的盐值
private static final int REPEAT = 5; //加密次数
/**
* 加密处理
* @param password 要加密的内容
* @return 加密后的数据
*/
public static String encode(String password){ //加密处理
String temp = password + "{" + SALT + "}"; //盐值不对外公布
byte data [] = temp.getBytes(); //将字符串变为字节数组
for (int i = 0; i < REPEAT; i ++) {
data = Base64.getEncoder().encode(data);
}
return new String(data);
}
/**
* 进行解密处理
* @param data 要解密的内容
* @return 解密后的原始数据
*/
public static String decode(String data){
byte[] password = data.getBytes();
for (int i = 0; i < REPEAT; i ++) {
password = Base64.getDecoder().decode(password);
}
return new String(password).replaceAll("\\{\\w+\\}" , "");
}
}
public class JavaAPIDemo {
public static void main(String[] args) throws ParseException {
//进行加密处理
String encode = StringUtil.encode("linlin");
System.out.println(encode);
//进行解密处理
System.out.println(StringUtil.decode(encode));
}
}
最好的做法是使用2-3种加密程序,同时再找到一些完全不可解密的加密算法
下一篇:比较器