Java常用类
1. Optional
反面示例:
interface IMessage{
void echo(String msg);
}
class Factory{
public static IMessage getInstance1(){
return (msg -> System.out.println("msg = " + msg)); // 正常
}
}
public class Demo {
public static void main(String[] args) {
IMessage message = Factory.getInstance1();
if(message!=null){ // 不为null才调用
message.echo("你好,小弟弟");
}
}
}
正面示例:
interface IMessage {
void echo(String msg);
}
class Factory {
public static Optional<IMessage> getInstance2() {
return Optional.of((msg -> System.out.println(msg))); // 保存到 Optional中 如果保存的为null的话,还是会发生空指针异常
}
}
public class Demo {
public static void main(String[] args) {
IMessage message = Factory.getInstance2().get();// 取出 Optional中的数据
message.echo("你好,小弟弟");
}
}
2. ThreadLocal
1. 常用方法
2. ThreadLocal怎么用?
下面我先举一个反面例子,加深大家的理解。
@Data
class Message {
public String content;
}
class MessagePrint { // 输出结果
public static void print() {
System.out.println("【MessagePrint】" + Resource.message.content);
}
}
/**
* 中间类
*/
class Resource {
static Message message;
}
/**
* 测试
* @author jiejie
* @date 2022/09/01
*/
public class Demo1 {
public static void main(String[] args) {
String[] values = {"你好,弟弟", "你好,妹妹", "你好,姐姐"};
for (String value : values) {
new Thread(() -> {
Resource.message = new Message();
Resource.message.setContent(value);
MessagePrint.print();
}).start();
}
}
结果:
修改Resource:
/**
* 中间类
*/
class Resource {
private static ThreadLocal<Message> threadLocal = new ThreadLocal<>();
public static Message getMessage() {
return threadLocal.get();
}
public static void setMessage(Message message) {
threadLocal.set(message);
}
public static void removeMessage() {
threadLocal.remove();
}
}
class MessagePrint { // 输出
public static void print() {
System.out.println("【MessagePrint】" + Resource.getMessage().content);
}
}
public class Demo1 {
public static void main(String[] args) {
String[] values = {"你好,弟弟", "你好,妹妹", "你好,姐姐"};
for (String value : values) {
new Thread(() -> {
Resource.setMessage(new Message());
Resource.getMessage().setContent(value);
MessagePrint.print();
}).start();
}
}
}
程序执行结果:
3. 定时任务
1. timer
简单用法
public class Demo {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("【定时任务】定时执行");
}
}, 1000, 2000);
}
}
执行结果:
【定时任务】定时执行
【定时任务】定时执行
【定时任务】定时执行
1.2 schedule和scheduleAtFixedRate有什么区别?
1.3:如果执行task发生异常,是否会影响其他task的定时调度?
1.4 Timer的一些缺陷?
2 JDK对定时任务调度的线程池支持:ScheduledExecutorService
我们直接看例子:
执行结果:
3 定时任务大哥:Quartz
3.1 核心:
任务 Job
触发器 Trigger
调度器 Scheduler
3.2 使用Quartz
导入依赖:
<!--quartz-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
创建任务类:
public class TestJob implements Job{
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("【定时任务】定时执行"+new Date());
}
}
测试
class TestScheduler {
public static void main(String[] args) throws SchedulerException {
// 获取默认任务调度器
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 定义Job(任务)实例
JobDetail testJob = JobBuilder.newJob(TestJob.class)
.withIdentity("测试任务").build();
// 定义触发器
Trigger simpleTrigger = TriggerBuilder.newTrigger()
.withIdentity("测试任务的触发器")
.startNow()
.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1))
.build();
// 使用触发器调度任务的执行
scheduler.scheduleJob(testJob, simpleTrigger);
scheduler.start();
}
}
经过上面的简单使用,我们再来了解下它的结构吧
图中可知,还有一种触发器 CronTrigger,下面简单使用一下吧。
Cron表达式用法
测试类 任务类不变,修改测试类即可
class TestScheduler {
public static void main(String[] args) throws SchedulerException {
// 获取默认任务调度器
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 定义Job(任务)实例
JobDetail testJob = JobBuilder.newJob(TestJob.class)
.withIdentity("测试任务").build();
// 定义触发器
CronTrigger cronTrigger = TriggerBuilder.newTrigger()
.withIdentity("name", "group")
.withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * ? * *")).build();
// 使用触发器调度任务的执行
scheduler.scheduleJob(testJob, cronTrigger);
scheduler.start();
}
}
4 Arrays
常用方法:
1 排序
public class Demo {
public static void main(String[] args) {
int[] arr = {1, 2, 19, 4, 5, 6, 7, 8, 9};
System.out.printf("【未排序前的数组:】%s \n", Arrays.toString(arr)); // Arrays.toString(arr) 数组转换成字符串
Arrays.sort(arr);
System.out.printf("【排序后的数组:】%s", Arrays.toString(arr));
}
}
// 执行结果
//【未排序前的数组:】[1, 2, 19, 4, 5, 6, 7, 8, 9]
//【排序后的数组:】[1, 2, 4, 5, 6, 7, 8, 9, 19]
2 判断是否相等
public class Demo2 {
public static void main(String[] args) {
int[] arrA = {1, 5, 7};
int[] arrB = {7, 5, 1};
System.out.println("【判断是否相等 -未排序】" + Arrays.equals(arrA, arrB));
Arrays.sort(arrA);
Arrays.sort(arrB);
System.out.println("【判断是否相等 -排序后】" + Arrays.equals(arrA, arrB));
System.out.println("【判断数组的大小关系 -排序后】" + Arrays.compare(arrA, arrB));
System.out.println("【判断数组的大小关系 -随机数组】" + Arrays.compare(new int[]{1, 2, 3}, arrB));
System.out.println("【判断数组的大小关系 -随机数组】" + Arrays.compare(new int[]{7, 8, 9}, arrB));
}
}
// 执行结果
//【判断是否相等 -未排序】false
//【判断是否相等 -排序后】true
//【判断数组的大小关系 -排序后】0
//【判断数组的大小关系 -随机数组】-1
//【判断数组的大小关系 -随机数组】1
3 二分查找
public class Demo3 {
public static void main(String[] args) {
int[] arrA = {1, 3, 5, 7, 9};// 模拟数组
int key = 9;// 需要查找的数据
int index = search(arrA, key);
System.out.println("index = " + index);
}
// 普通 循环查询,未查找到返回-1
private static int search(int[] arrA, int key) {
for (int i = 0; i < arrA.length; i++) {
if (arrA[i] == key) {
return i;
}
}
return -1;
}
}
然后我们再来看看,二分查找。
/**
* 二分查找
*/
private static int twoPoints(int[] arrA, int key) {
Arrays.sort(arrA);
System.out.println("【排序后的数组:】"+Arrays.toString(arrA));
// 开始索引
int start = 0;
// 结束索引
int end = arrA.length - 1;
while (start <= end) {
// 位运算 这里以5为例 101(5) >>>1 10(2) mid(中间的下标)
int mid = start+end >>> 1;
int midVal = arrA[mid];
// 用中间值的key比较,中间值小的话,说明我们需要查找的数据在右边,中间值+1赋值start
if (midVal < key) {
start = mid + 1;
}// 用中间值的key比较,中间值打的话,说明我们需要查找的数据在右边,中间值-1赋值end
else if (midVal > key) {
end = mid - 1;
} else {
return mid;
}
}
// 未找到
return -1;
}
4 比较器
4.1 比较器出现的原因
public static void sort(Object[] a)
@AllArgsConstructor
@Data
class Book{
String name;
double price;
}
public class 比较器 {
public static void main(String[] args) {
Book[] books= new Book[] {
new Book("Java入门到入土",89.0),
new Book("Python入门到入土",78.0),
new Book("前端入门到入土",68.0)
};
Arrays.sort(books);
}
}
执行程序: 可以发现,程序执行报错了。类转换异常
Exception in thread "main" java.lang.ClassCastException: class look.word.arrays.Book cannot be cast to class java.lang.Comparable (look.word.arrays.Book is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')
at java.base/java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:320)
at java.base/java.util.ComparableTimSort.sort(ComparableTimSort.java:188)
at java.base/java.util.Arrays.sort(Arrays.java:1041)
at look.word.arrays.比较器.main(比较器.java:26)
4.2 Comparable
示例:
@AllArgsConstructor
@Data
class Book implements Comparable<Book>{
String name;
double price;
@Override
public int compareTo(Book book) {
if (this.price > book.price){
return 1;
} else if (this.price < book.price) {
return -1;
}
return 0;
}
}
执行程序:
【Book类继承比较器比较后的结果】
[Book(name=前端入门到入土, price=68.0),
Book(name=Python入门到入土, price=78.0),
Book(name=Java入门到入土, price=89.0)]
4.3 Comparator
示例代码:
@AllArgsConstructor
@Data
class books {
String name;
double price;
}
public class 比较器2 {
public static void main(String[] args) {
books[] books = new books[]{
new books("Java入门到入土", 89.0),
new books("Python入门到入土", 78.0),
new books("前端入门到入土", 68.0)
};
Comparator<books> comparator = (books1, books2) -> {
if (books1.price > books2.price) {
return 1;
} else if (books1.price < books2.price) {
return -1;
}
return 0;
};
Arrays.sort(books, comparator.reversed()); // comparator.reversed() 是反转的意思
System.out.println("【books类继承比较器比较后的结果】\n" + Arrays.toString(bookss));
}
}
程序执行结果:
【books类继承比较器比较后的结果】
[books(name=Java入门到入土, price=89.0),
books(name=Python入门到入土, price=78.0),
books(name=前端入门到入土, price=68.0)]
5 StringBuffer
传统面向过程做法
/**
* 传统面向过程实现
**/
public class Demo {
public static void main(String[] args) {
StringBuffer buffer = new StringBuffer(26);
for (int i = 'a'; i <= 'z'; i++) {
buffer.append((char) i);
}
System.out.println("【初始的数据】" + buffer);
System.out.println("【逆序输出】" + buffer);
System.out.println("【删除前5个】" + buffer.delete(0, 5));
}
}
**范例:**通过面向对象的方式进行程序的开发
interface IContent { // 接口先行
String content();
String reverse();
String delete(int start, int end);
}
class StringContent implements IContent {
private StringBuffer buffer = new StringBuffer(26);
public StringContent() {
for (int i = 'a'; i <= 'z'; i++) {
buffer.append((char) i);
}
}
public String content() {
return buffer.toString();
}
public String reverse() {
return buffer.reverse().toString();
}
public String delete(int start, int end) {
return buffer.delete(start, end).toString();
}
}
class Factory { // 工厂获取实例
private Factory() {}
public static StringContent getInstance() {
return new StringContent();}
}
public class Demo2 {
public static void main(String[] args) {
StringContent content = Factory.getInstance();
System.out.println("【初始的数据】" + content.content());
System.out.println("【逆序输出】" + content.reverse());
System.out.println("【删除前5个】" + content.delete(0, 5));
}
}
6 反射
1. 出现的原因
范例:观察传统的类的使用行为
class Book{
public void read(){
System.out.println("认真学习java书籍!");
}
}
public class Demo {
public static void main(String[] args) {
Book book = new Book(); // 实例化对象
book.read(); // 调用实例的方法
}
}
// 执行结果: 认真学习java书籍!
2. 反射的入口
java.lang.Class
获取类Class对象的四种方式:
- 调用运行时类本身的.class属性
Class<String> stringClass = String.class;
- 通过运行时类的对象获取
Class<? extends String> aClass = new String().getClass();
- 通过Class的静态方法获取:体现反射的动态性
try {
Class<?> aClass1 = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
- 通过类的加载器
ClassLoader classLoader = this.getClass().getClassLoader(); // 获取类加载器
Class<?> aClass1 = classLoader.loadClass("java.lang.String");
3. 获取成员变量
@Data
class Books{
String name;
public Integer age;
private Integer gender;
protected String salt;
}
public class 属性 {
public static void main(String[] args) {
Class<Books> booksClass = Books.class;
// 获取所有属性 包括私有的
Field[] fields = booksClass.getDeclaredFields();
for (Field field : fields) {
// 设置访问无障碍
field.setAccessible(true);
System.out.print("【修饰符】" + Modifier.toString(field.getModifiers()));
System.out.print("【\t变量的类型】" + field.getType());
System.out.print("【\t属性的的名称】 = " + field.getName()+"\n");
}
}
}
4. 调用方法
class Book1 {
public void init() {
System.out.println("初始图书" );
}
public void read(String name) {
System.out.println("读了" + name);
}
}
public class 方法 {
public static void main(String[] args) throws Exception {
Class<Book1> bookClass = Book1.class; // 获取Class对象
Method init = bookClass.getMethod("init"); // 获取指定方法
init.invoke(bookClass.newInstance(),null); // 执行实例无参方法
Method read = bookClass.getMethod("read", String.class); // 获取指定方法
read.invoke(bookClass.newInstance(),"java图书"); // 执行实例有参方法
Method[] methods = bookClass.getMethods();
for (Method method : methods) { // 遍历所有方法
System.out.println("method = " + method);
}
}
}