文档章节

java常用开发支持类库

哼着我的小调调
 哼着我的小调调
发布于 07/10 20:16
字数 2590
阅读 46
收藏 0

「深度学习福利」大神带你进阶工程师,立即查看>>>

UUID类

UUID是一个生成无重复字符串的程序类(JDK1.5之后出现),这个程序类的主要功能是根据时间戳实现一个自动的无重复的字符串定义(无重复指的是出现重复的概率极低)。

一般在获取UUID时往往都是随机生成一个的内容,可以通过如下方式获取:

  • 获取UUID对象:public static UUID randomUUID()
  • 根据字符串获取UUID内容:public static UUID fromString(String name)
public class JavaAPIDemo {
    public static void main(String[] args) {
        UUID uid = UUID.randomUUID();
        System.out.println(uid.toString());
    }
}
随机生成一个UUID:
d752e1dc-181f-44e7-8ce3-b2369cb14660

对于一些文件进行自动命名处理的情况,UUID非常方便

Optional类

Optional类的主要功能是进行null的相关处理,例如:为了防止程序中出现空指针异常,往往追加有null的验证。

范例:传统的引用传递

interface IMessage{
    String getContent();
}
class IMessageImpl implements IMessage{

    @Override
    public String getContent() {
        return "你好";
    }
}
class MessageUtil{
    private MessageUtil(){}
    public static void useMessage(IMessage msg){
        //如果不进行判断,那么可能会导致空指针异常
		if (msg!=null)
            System.out.println(msg.getContent());
    }
    public static IMessage getMessage(){
//        return new IMessageImpl();
        return null;
    }
}
public class JavaAPIDemo {
    public static void main(String[] args) {
        MessageUtil.useMessage(MessageUtil.getMessage());
    }
}

在引用接收的一方往往都是被动的进行判断,所以为了解决这种被动的处理操作,Java类中就提供了Optional类,这个类可以实现null的处理操作。

  • 返回空数据:public static<T> Optional empty()
  • 获取数据:public T get()
  • 保存数据,但是不允许出现null:public static <T> Optional<T> of(T value),如果出现null,则会抛出NullPointerException异常
  • 保存数据,允许为空:public static <T> Optional<T> ofNullable(T value)
  • 空的时候返回其他数据:public T orElse(T other)

修改上述程序:

import java.util.Optional;

interface IMessage{
    String getContent();
}
class IMessageImpl implements IMessage{

    @Override
    public String getContent() {
        return "你好";
    }
}
class MessageUtil{
    private MessageUtil(){}
    public static void useMessage(IMessage msg){
        if (msg!=null)
            System.out.println(msg.getContent());
    }
    public static Optional<IMessage> getMessage(){
        IMessageImpl iMessage = new IMessageImpl();
        return Optional.of(iMessage);
    }
}
public class JavaAPIDemo {
    public static void main(String[] args) {
        IMessage iMessage = MessageUtil.getMessage().get();
        MessageUtil.useMessage(iMessage);
    }
}
结果:你好

如果现在数据保存的内容为null,则就会在保存处出现空指针异常: 例如:

    public static Optional<IMessage> getMessage(){
        IMessage message=null;
        return Optional.of(message);//有对象
    }

由于Optional类中也有允许保存null的方法(Optional.ofNullable()),所以在数据获取时也可以进行null的处理,如果为null,则在使用get()获取数据时就会出现“NoSuchElementException”异常,所以此时可以更换为orElse()方法

处理null的方法

class MessageUtil{
    private MessageUtil(){}
    public static void useMessage(IMessage msg){
        if (msg!=null)
            System.out.println(msg.getContent());
    }
    public static Optional<IMessage> getMessage(){
        return Optional.ofNullable(null);
    }
}
public class JavaAPIDemo {
    public static void main(String[] args) {
        IMessage iMessage = MessageUtil.getMessage().orElse(new IMessageImpl());
        MessageUtil.useMessage(iMessage);
    }
}

在所有引用数据类型的操作处理之中,null是一个重要的技术问题,所以来说JDK1.8后提供的Optional类对于null的处理很有帮助,同时也是在日后进行项目开发时常用的程序类。

ThreadLocal类

解决核心资源与多线程并发访问的处理情况

范例:消息发送处理


class Channel{//消息发送的通道
    private Channel(){}
    public static Message message;
    public static void setMessage(Message msg){
        message = msg;
    }
    public static void send(){
        System.out.println("【消息发送】"+message.getInfo());
    }
}
class Message{//消息实体类
    private String info;
    public void setInfo(String info) {
        this.info = info;
    }
    public String getInfo() {
        return info;
    }
}
public class JavaAPIDemo {
    public static void main(String[] args) {
        Message msg = new Message();//实例化消息主体对象
        msg.setInfo("你好");//设置要发送的内容
        Channel.setMessage(msg);//设置要发送的消息
        Channel.send();//消息发送
    }
}

对于当前的程序采用的是一种单线程的模式来进行处理的;那么如果再多线程的状态下能否实现安全一致的操作效果呢?为此将启动三个线程进行处理。

范例:多线程的影响


class Channel{//消息发送的通道
    private Channel(){}
    public static Message message;
    public static void setMessage(Message msg){
        message = msg;
    }
    public static void send(){
        System.out.println(Thread.currentThread().getName()+"【消息发送】"+message.getInfo());
    }
}
class Message{//消息实体类
    private String info;
    public void setInfo(String info) {
        this.info = info;
    }
    public String getInfo() {
        return info;
    }
}
public class JavaAPIDemo {
    public static void main(String[] args) {
        new Thread(()->{
            Message msg=new Message();//实例化消息主体对象
            msg.setInfo("第1个线程的消息");//设置要发送的内容
            Channel.setMessage(msg);//设置要发送的消息
            Channel.send();//发送消息
        },"消息发送者A").start();
        new Thread(()->{
            Message msg=new Message();//实例化消息主体对象
            msg.setInfo("第2个线程的消息");//设置要发送的内容
            Channel.setMessage(msg);//设置要发送的消息
            Channel.send();//发送消息
        },"消息发送者B").start();
        new Thread(()->{
            Message msg=new Message();//实例化消息主体对象
            msg.setInfo("第3个线程的消息");//设置要发送的内容
            Channel.setMessage(msg);//设置要发送的消息
            Channel.send();//发送消息
        },"消息发送者C").start();
    }
}

运行结果:
消息发送者C【消息发送】第2个线程的消息
消息发送者B【消息发送】第2个线程的消息
消息发送者A【消息发送】第2个线程的消息

可以看出多线程发送产生很大的影响

在保持Channel(所有的发送通道)核心结构不改变的情况下,需要到考虑到每个线程的独立操作问题。那么这样的情况下,对于Channel类而言,除了要保留有发送的消息之外,还需要存放一个每一个线程的标记(当前线程),这时可以通过ThreadLocal类来实现。在ThreadLocal类中提供有如下操作方法:

  • 构造方法:public ThreadLocal()
  • 设置属性:public void set(T value
  • 取出数据:public T get()
  • 移除数据:public void remove()

只需要改这一个类,其他的不变

class Channel{//消息发送的通道
    private Channel(){}
    public static final ThreadLocal<Message> THREAD_LOCAL = new ThreadLocal<>();
    public static void setMessage(Message msg){
        THREAD_LOCAL.set(msg);
    }
    public static void send(){
        System.out.println(Thread.currentThread().getName()+"【消息发送】"+THREAD_LOCAL.get().getInfo());
    }
}
运行结果:
消息发送者C【消息发送】第3个线程的消息
消息发送者A【消息发送】第1个线程的消息
消息发送者B【消息发送】第2个线程的消息

每一个线程通过ThreadLocal只允许保存一个数据。

定时器 Timer与TimerTask

定时器的主要操作就是进行定时任务的处理。在JDK1.3后提供了定时任务的支持,但是这种任务的处理只实现了间隔触发的操作效果。

如果要实现定时的处理操作主要需要有一个定时操作的主体类,以及一个定时任务的控制。可以使用两个类实现:

  • java.util.TimerTask类:实现定时任务处理;
  • java.util.Timer类:进行任务的启动,启动的方法:
    • 任务启动:public void schedule(TimerTask task, long delay)、延迟单位为毫秒;
    • 间隔触发:`public void schedule(TimerTask task, long delay, long period)``;

  time.schedule(new MyTask(),1000);//1s后启动
        //间隔触发
        time.scheduleAtFixedRate(new MyTask(),100,1000);//100毫秒后启动,每秒执行一次
    }
}

这种定时是由JDK最原始的方式提供的支持,但是如果使用此类设置定时会非常复杂。

Base64加密工具

一般来说,加密往往都伴随着解密,所谓的加密或者解密都需要有一些规则。在JDK1.8开始提供有一组新的加密处理操作类,Base64处理。

  • java.util.Base64.Encoder:进行加密操作;
    • 加密处理:`public byte[] encode(byte[] src)``;
  • java.util.Base64.Decoder:进行解密操作;
    • 解密处理:public byte[] decode(byte[] src)

范例:实现加密与解密操作

import java.util.Base64;

public class JavaAPIDemo {
    public static void main(String[] args) {
        String msg = "你好";//要发送的信息
        //Base64操作的是字节数组
        //加密处理
        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);
    }
}
运行结果:
5L2g5aW9
你好

注意:使用字符串接收encMsg的时候,必须使用new String()将加密后的字节码数组保存,不能使用toString()方法,因为Base64加解密是一种转换编码格式的原理

toString()与new String()的区别

  • str.toString是调用了b这个object对象的类的toString方法。一般是返回这么一个String:[class name]@[hashCode]。
  • new String(str)是根据parameter是一个字节数组,使用java虚拟机默认的编码格式,将这个字节数组decode为对应的字符。若虚拟机默认的编码格式是ISO-8859-1,按照ascii编码表即可得到字节对应的字符。
  • 使用
    • new String()一般使用字符转码的时候,byte[]数组的时候
    • toString()将对象打印的时候使用

虽然Base64可以实现加密和解密的处理,但是其由于是一个公版的算法,所以如果直接对数据进行加密并不安全,所以可以对其进行盐值操作。

import java.util.Base64;

public class JavaAPIDemo {
    public static void main(String[] args) {
        String salt = "java";
        String msg = "你好"+"【"+salt+"】";//要发送的信息
        //Base64操作的是字节数组
        //加密处理
        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);
    }
}
运行结果:
5L2g5aW944CQamF2YeOAkQ==
你好【java】

即便现在有盐值实际上发现加密的效果也不是很好,更好的做法是多次加密。

范例:复杂加密

import java.util.Base64;
class StringUtil{
    private static final String SALT = "java";//公共盐值,一旦使用,不可更改
    private static final int REPEAT = 4;//重复加密次数

    /**
     * 加密处理
     * @param str 要加密的字符串
     * @return 加密后的数据
     */
    public static String encode(String str){
        String temp = str+"【"+SALT+"】";
        byte[] data = temp.getBytes();//将字符串变为字节数组
        for (int x = 0; x < REPEAT; x++) {
            data = Base64.getEncoder().encode(data);
        }
        return new String(data);
    }

    /**
     * 解密处理
     * @param str 要解密的字符串
     * @return 解密后的结果
     */
    public static String decode(String str){
        byte[] data = str.getBytes();//将字符串转化为字节数组
        for (int x = 0; x < REPEAT; x++) {
            data = Base64.getDecoder().decode(data);
        }
        String decode = new String(data);
        return decode.replaceAll("\\【\\w+\\】","");//正则处理,或者字符串切割去掉盐值
    }
}
public class JavaAPIDemo {
    public static void main(String[] args) {
        String msg = "你好";//要发送的信息
        String encode = StringUtil.encode(msg);
        //加密
        System.out.println(encode);
        System.out.println("================");
        //解密
        String decode = StringUtil.decode(encode);
        System.out.println(decode);
    }
}

运行结果:
VGxWM2VWcDZWbWhXZW1zd1RrVk9VbGxYTVVkTmJHeHNWREJHY2xWVU1Eaz0=
================
你好

最好的做法就是使用2-3种加密程序,同时再找到一些完全不可解密的加密算法。

哼着我的小调调
粉丝 1
博文 23
码字总数 59599
作品 0
郑州
私信 提问
加载中
请先登录后再评论。
Netty那点事(三)Channel与Pipeline

Channel是理解和使用Netty的核心。Channel的涉及内容较多,这里我使用由浅入深的介绍方法。在这篇文章中,我们主要介绍Channel部分中Pipeline实现机制。为了避免枯燥,借用一下《盗梦空间》的...

黄亿华
2013/11/24
2W
22
访问安全控制解决方案

本文是《轻量级 Java Web 框架架构设计》的系列博文。 今天想和大家简单的分享一下,在 Smart 中是如何做到访问安全控制的。也就是说,当没有登录或 Session 过期时所做的操作,会自动退回到...

黄勇
2013/11/03
3.5K
8
Flappy Bird(安卓版)逆向分析(一)

更改每过一关的增长分数 反编译的步骤就不介绍了,我们直接来看反编译得到的文件夹 方法1:在smali目录下,我们看到org/andengine/,可以知晓游戏是由andengine引擎开发的。打开/res/raw/at...

enimey
2014/03/04
6.1K
18
浅入浅出Android(003):使用TextView类构造文本控件

基础: TextView是无法供编辑的。 当我们新建一个项目MyTextView时候,默认的布局(/res/layout/activity_main.xml)中已经有了一个TextView: <TextView 运行效果如下: 修改其文本内容...

樂天
2014/03/22
687
1
beego API开发以及自动化文档

beego API开发以及自动化文档 beego1.3版本已经在上个星期发布了,但是还是有很多人不了解如何来进行开发,也是在一步一步的测试中开发,期间QQ群里面很多人都问我如何开发,我的业余时间实在...

astaxie
2014/06/25
2.7W
22

没有更多内容

加载失败,请刷新页面

加载更多

Vue视频播放器 vue-video-player

Vue视频播放器 vue-video-player 本篇主要记录一下 在 vue 项目中 如何使用 vue-video-player 来作为视频播放器,由于最近在做博客的 轻松一刻模块 所以拿这个尝试一下 在此纪录一下 以及遇到...

AskaJohnny
7分钟前
5
0
Python是什么,Python语言及其特点简介

虽然软件产业的历史相对于人类历史只是白驹过隙,但世界上却存在非常多的编程语言,「Python」 就是其中之一。 Python 语言算得上一门“古老”的编程语言,Python 流行这么久,必然有它的独到...

前端老司机
16分钟前
11
0
serve 和 hhtp-server 对比

两个都是一个静态资源工具 npm i serve http-server -g https://github.com/http-party/http-server#readme https://github.com/vercel/serve#readme 由于遇到了cors问题, 目前选择http-se......

阿豪boy
18分钟前
8
0
java开发之阿里云接口发送短信验证码

随着互联网的兴起,各行各业的需求都在不断的增加。随着业务的扩大,企业给用户发送短信验证码的业务,也是如火如荼。在这里,calvin给各位开发者推荐阿里云短信平台。原因有二:1.接入较简单...

Arisono
28分钟前
9
0
如何从我的应用程序在Android的网络浏览器中打开URL? - How can I open a URL in Android's web browser from my application?

问题: How to open an URL from code in the built-in web browser rather than within my application? 如何通过内置Web浏览器而不是应用程序中的代码打开URL? I tried this: 我尝试了这个...

javail
28分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部