Java常用类的使用

spring定时任务示例程序 spring定时任务的一个简单示例程序,包括需要引入的jar包,eclipse源代码直接压缩的,解压导入到自己的eclipse中即可,本人所用的是eclipseJ2EE版本 立即下载

Java常用类

1. Optional

在我们的开发中, NullPointerException 可谓是随时随处可见,为了避免空指针异常,我们常常需要进行 一

些防御式的检查,所以在代码中常常可见 if(obj != null) 这样的判断。幸好在JDK1.8中,java为我们提供了

一个Optional类,Optional类能让我们省掉繁琐的非空的判断。下面先说一下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("你好,小弟弟");
    }
}

 

这里想要表达的意思就是,保存到Optional中的数据为null,只会在赋值是出现空指针异常,而不会等到调用是才出现,增强了业务的健壮性。

2. ThreadLocal

​ 从名字我们就可以看到 ThreadLocal 叫做本地线程变量,意思是说, ThreadLocal 中填充的的是当前线程的变量,该变量对其他线程而言是封闭且隔离的, ThreadLocal 为变量在每个线程中创建了一个副本,这样每个线程都可以访问自己内部的副本变量。

​ 从字面意思很容易理解,但是实际角度就没那么容易了,作为一个面试常问的点,使用场景也是很丰富。

  • 1、在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。
  • 2、线程间数据隔离
  • 3、进行事务操作,用于存储线程事务信息。
  • 4、数据库连接, Session 会话管理。

1. 常用方法

2. ThreadLocal怎么用?

下面我先举一个反面例子,加深大家的理解。

启动三个线程,遍历values数组,然后看他们的输出结果。

 

@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();
        }
    }

结果:

可以看到,输出的结果怎么是一样的呢,我们不是遍历输出的吗。这就要谈到我们的线程安全的问题,简单来说,多个线程同时对某个对象进行赋值就会存在线程安全的问题,其实相对于这个问题,我们可以加锁来解决这个问题。今天我们使用另外一个方法,就是上面提到的ThreadLocal。请看:

修改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();
        }
    }
}

程序执行结果:

可以看到,我们的目的实现了,有没有发现输出的顺序与values数组的顺序并不一致,这是由于我们线程启动的顺序决定的。

我们这里就体现了线程间对于变量的隔离。

3. 定时任务

在开发过程中,经常性需要一些定时或者周期性的操作。而在Java中则使用Timer对象完成定时计划任务功能。

定时计划任务功能在Java中主要使用的就是Timer对象,它在内部使用多线程的方式进行处理,所以Timer对象一般又和多线程技术结合紧密。

由于Timer是Java提供的原生Scheduler(任务调度)工具类,不需要导入其他jar包,使用起来方便高效,非常快捷。

参数说明:

  • task :所要执行的任务,需要extends TimeTask override run()
  • time/firstTime :首次执行任务的时间
  • period :周期性执行Task的时间间隔,单位是毫秒
  • delay :执行task任务前的延时时间,单位是毫秒 很显然,通过上述的描述,我们可以实现: 延迟多久后执行一次任务;指定时间执行一次任务;延迟一段时间,并周期性执行任务;指定时间,并周期性执行任务;

1. timer

  1. 实现TimerTask (需要执行什么任务 )的run方法, 明确要做什么
    可以继承实现, 也可用匿名内部类
  2. new 一个Timer
  3. 调用Timer实例的 schedule 或 scheduleAtFixedRate 方法
    将TimerTask放入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有什么区别?

scheduleAtFixedRate:每次执行时间为上一次任务开始起向后推一个period间隔,也就是说下次执行时间相对于上一次任务开始的时间点,因此执行时间不会延后,但是存在任务并发执行的问题( 简单来说,就是当任务阻塞,下次任务开始的时间不会受阻塞影响,而推迟下次任务执行时间。 )。

schedule: 每次执行时间为上一次任务结束后推一个period间隔 ,也就是说下次执行时间相对于上一次任务结束的时间点,因此执行时间会不断延后(回受阻塞影响)。

1.3:如果执行task发生异常,是否会影响其他task的定时调度?

如果TimeTask抛出RuntimeException,那么Timer会停止所有任务的运行!

1.4Timer的一些缺陷?

​ 前面已经提及到Timer背后是一个 单线程 ,因此Timer存在管理并发任务的缺陷:所有任务都是由同一个线程来调度,所有任务都是串行执行,意味着同一时间只能有一个任务得到执行,而前一个任务的延迟或者异常会影响到之后的任务。 其次,Timer的一些调度方式还算比较简单,无法适应实际项目中任务定时调度的复杂度。

2 JDK对定时任务调度的线程池支持:ScheduledExecutorService

​ 由于Timer存在的问题,JDK5之后便提供了基于线程池的定时任务调度: ScheduledExecutorService。 设计理念:每一个被调度的任务都会被线程池中的一个线程去执行,因此任务可以并发执行,而且相互之间不受影响。

我们直接看例子:

执行结果:

【定时任务】定时执行Fri Sep 02 12:54:02 CST 2022

【定时任务】定时执行Fri Sep 02 12:54:04 CST 2022

【定时任务】定时执行Fri Sep 02 12:54:06 CST 2022

3 定时任务大哥:Quartz

虽然ScheduledExecutorService对Timer进行了线程池的改进,但是依然无法满足复杂的定时任务调度场景。因此OpenSymphony提供了强大的开源任务调度框架:Quartz。Quartz是纯Java实现,而且作为 Spring的默认调度框架 ,由于Quartz的强大的调度功能、灵活的使用方式、还具有 分布式集群能力 ,可以说Quartz出马,可以搞定一切定时任务调度!

3.1 核心:

任务 Job

我们想要调度的任务都必须实现 org.quartz.job 接口,然后实现接口中定义的 execute( ) 方法即可,类似于 TimerTask 。

触发器 Trigger

Trigger作为执行任务的调度器。我们如果想要凌晨1点执行备份数据的任务,那么 Trigger 就会设置凌晨1点执行该任务。其中 Trigger 又分为 SimpleTrigger 和 CronTrigger 两种

调度器 Scheduler

Scheduler为任务的调度器,它会将任务 Job 及触发器 Trigger 整合起来,负责基于 Trigger 设定的时间来执行 Job

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

Arrays类位于 java.util 包中,主要包含了操纵数组的各种方法。

常用方法:

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 判断是否相等

需要一模一样的数组,执行结果才会为True

判断大小关系:大于(1)、等于(0)、小于(-1)

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 二分查找

二分查找在大数据量的场景下,性能非常好。

下面举个栗子:

  • 试想一下,要是我们的arrA数组的数据量非常大,达到了百万级别甚至更多,我们想要在里面找到某个数据,会遍历数组很多次,时间复杂度O(n)

 

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;
    }
}

 

 

然后我们再来看看,二分查找。

注意,使用二分查找的前提下, 要保证数组的有序性(先排序)

  • Arrays.binarySearch(数组,key);(Arrays提供的二分查找)
    /**
         * 二分查找
         */
        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 比较器出现的原因

​ 在Java项目开发的机制之中,比较器是一种最为常见的功能,同时在整个的Java类集实现架构之中,比较器都有着非常重要的地位,但是首先应该知道为什么要使用比较器?﹒通过之前的讲解应该已经发现在Java里面提供有一个所谓的Arrays类,这个Arrays类提供有大量的数组有关的操作方法,而其中,可以发现这样的一个方法定义:

public static void sort(Object[] a)

发现Arrays类也可以直接实现对象数组的排序处理,于是下面就按照此方法的规则进行程序的编写。范例:实现一个对象数组的排序﹐

@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)

​ 在程序执行的过程之中出现有一个“ ClassCastException ”异常,这种异常所描述的就是对象转换异常,这里面直接提示给用户“不能够将Book类的对象实例转为Comparable”。那么为什么现在会出现这样的异常呢?

​ 如果说现在给定的是一个整型数组,那么如果要想确定数组之中的元素彼此之间的大小关系,直接利用各种关系运算符即可,但是问题是此时所给出的是一个对象数组,对象数组里面所包含的内容一个个堆内存的信息,那么请问堆内存的信息如何进行大小关系的比较呢?。

​ 很明显,堆内存无法直接进行大小关系的比较,如果要的进行排序处理,严格意义上来讲应该使用是堆内存中属性的内容来进行大小关系确认,而这个属性内容的确认就必须采用比较器来支持,而在Java里面支持有两种比较器: Comparable、Comparator 。

4.2 Comparable

要想自定义的类,实现可以比的效果,可以实现我们的Comparable接口,实现其compareTo方法。定义比较规则。

示例:

@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;
    }
}

 

 执行程序:

可以看到,这次程序执行没有出错,并且是升序排序的。如若修改排序规则,修改每次判断的返回值即可。

  • String类就实现了 Comparable 这个接口,也就是说String类支持排序。
    【Book类继承比较器比较后的结果】
     [Book(name=前端入门到入土, price=68.0), 
     Book(name=Python入门到入土, price=78.0),
     Book(name=Java入门到入土, price=89.0)]

    4.3 Comparator

    需要使用 Comparator 是一个带有@FunctionalInterface,也就是说它是一个函数式接口,可以使用Lambda表达式,也可以使用匿名类部类的方式去定义我们的比较规则。

    示例代码:

     

    @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)]

 Comparator 除了基本的排序支持之外,其内部实际上也存在有大量的数据排序的处理操作,例如: reversed(),如果现在使用的是Comparable接口实现这样的反转那么必须进行大量系统源代码的修改,法来进行配置,所以灵活度更高。

​ 总结:请解释两种比较器的区别?

  • java.Jang.Comparable:是在类定义的时候实现的接口,该接口只存在有一个compareTo()方法用于确定大小关系;
  • java.utilComparator:是属于挽救的比较器,除了可以实现排序的功能之外,在JDK 1.8之后的版本里面还提供有更多方便的数组操作的处理功能。

5 StringBuffer

定义一个 StringBuffer类对象,然后通过append()方法向对象中添加26个小写字母,要求每次只添加一次,共添加26次,然后按照逆序的方式输出,并且可以删除前5个字符。

传统面向过程做法

/**
 * 传统面向过程实现
 **/
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. 出现的原因

​ Java编程开发之所以会存在有反射机制,最为重要的原因是可以使Java编写代码更加的灵活,而这种灵活如果要想彻底的领悟,那么也需要通过大量的苦练才可以得到,当你已经可以熟练使用反射之后,那么就可以设计出更加结构性强,且可重用性更高的程序代码,在Java里面存在有很多的开发框架,而之所以可以提供大量开发框架,主要的原因也在于反射机制。

Java的反射机制指的是通过“反方向”的操作来实现类的相关处理,那么既然要有“反”则一定会有“正”,按照传统的开发的行为模式来讲,如果要想进行一个类的操作,那么是需要根据类进行对象的实例化,随后再通过实例化对象实现类中方法的调用处理,现在给出如下代码。

范例:观察传统的类的使用行为

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书籍!

 

 

以上的处理操作是一种正向的处理行为,但是如果是反向操作,则就意味着可以根据实例化对象获取相关的信息来源,在Java里面所有的类实际上都属于Object子类,那么在Object类中就提供有一个重要的方法,这个方法可以获取“反”的信息:

2. 反射的入口

java.lang.Class

对每一种对象,JVM 都会实例化一个 java.lang.Class 的实例,java.lang.Class 为我们提供了在运行时访问对象的属性和类型信息的能力。Class 还提供了创建新的类和对象的能力。最重要的是,Class 是调用其他反射 API 的入口,我们必须先获得一个 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. 获取成员变量

java.lang.Class 也提供了许多获取成员变量的方法:

  • public Field[] getDeclaredFields() 获取所有的属性(包括私有的)
  • public Field[] getFields() 获取所有public 修饰的属性

当然每个成员变量有 类型 和 值 。 java.lang.reflect.Field 为我们提供了获取当前对象的成员变量的类型,和重新设值的方法。

提供了两个方法获去变量的类型:

  • field.getModifiers(): 获取属性的修饰符

  • Field.getName():获取属性的的名称

  • Field.getType():返回这个属性的类型

  • Field.getGenericType():如果当前属性有签名属性类型就返回,否则就返回 Field.getType()

@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.getMethods(): 获取所有的方法
Class.getMethod("方法名","方法的参数列表数据类型");
Class.getParmenterTypes(); // 获取参数列表
Class.getReturnType(); //返回类型
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);
        }
    }
}

 

 

 

 

 

 

FIFO的工作原理及其设计 FIFO( First Input First Output)简单说就是指先进先出。FIFO存储器是一个先入先出的双口缓冲器,即第一个进入其内的数据第一个被移出,其中一个口是存储器的输入口,另一个口是存储器的输出口。对于单片FIFO来说,主要有两种结构:触发导向结构和零导向传输结构。触发导向传输结构的FIFO是由寄存器阵列构成的,零导向传输结构的FIFO是由具有读和写地址指针的双口RAM构成。FIFO与普通RAM存储器的是没有外部读写地址线(指针),使用方便,但。 阅读详情

相关推荐

2 海康视觉平台VisionMaster 上手系列:大纲及准备

海康视觉平台VisionMaster 大纲,课前准备 快速入门 工业机器视觉 机器视觉

HuangGong2022的博客 1万+

Java 排序遇到的神坑,我替你踩了!

作者:nxlhero来源:https://blog.51cto.com/nxlhero/2515850 问题描述 一个开发人员写了一段明显有问题的排序代码,大致如下: import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; public class Test { public static void main(String[]

Java技术栈,分享最主流的Java技术 726

基于BQ24610的24V电池充电板

转自我的博客 本文的主要目的在于传播基本的阅读datasheet的能力,以及PCB设计需要注意的基本问题。 本次需要设计的是24V动力锂电池充电电路。 原理图设计 参考官方参考电路 为了快速设计电路,自然是参考官方参考电路,选择Typical Application。 做细微的参数调整 由于我们的需求是给24V的电池充电,所以需要稍微修改一下原理图,接下来需...

greedyhao的博客 1万+

eclipse中搭建springboot学习(13)---定时任务

启动类 package com.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletC...

Gr_lbxx的博客 504

PSOC Creator 入门教程超详细

最近工作原因需要使用到赛普拉斯的一款芯片,奈何以前没有用过,所以趁这次也学习了一些简单的用法,总结一下,希望能帮到有需要朋友,因为网上关于这方面的文章少的可怜,详细点的更是少之又少!废话少说,正文开始.

qm_mq的博客 5746

桌面云架构讲解(VDI、IDV、VOI/TCI、RDS)

什么是云桌面桌面云是虚拟化技术成熟后发展起来的一种应用,桌面云通常也称为云桌面、VDI等桌面云中的云一般指的是企业的数据中心,通过在数据中心的服务器上安装若干个虚拟机,这个虚拟机就是桌面;但是终端无法直接连接到这个虚拟机(云桌面),因此就需要通过技术将就虚拟机变为桌面云发放出来;发放出来之后只需要瘦客户端(PC、手机、瘦客户机等)连接到数据中心的云桌面服务器平台,最终就可以连接到桌面来进行使用云桌面的优势终端与数据信息分离,数据在后台集中处理和存储 ,数据实现统一管理。

m0_49864110的博客 3万+

JAVA常用类总结,使用API

在学习 基础语法、类与对象之后。Java提供了丰富的基础类库,通过这些类库可以提高开发效率,降低开发难度。因此,对于一个初学者来说,掌握Java基础类库的一些常用类很重要。 可以通过查看Java API查看基础类库,以及一些常用的类。在经历了一些练习之后,感觉可以从以下几方面使用API 类的性质(是否为抽象类,接口,final类) 类是否继承了某个类,或继承某个接口(方法,属性的继承) 类的属性...

ZHOUJIAN_TANK的博客 367

从Overleaf上导出Latex论文发布到arxiv详细教程(常见问题与解决)

如果是做cv的论文请选择“Computer Vision and Pattern Recognition”,选择“Artificial Intelligence”可能会被on hold,貌似这个指的是传统的人工智能?我用公司邮箱注册发布一篇论文,一个多月还是“on hold”状态,换成edu邮箱第二天就被发布了。3、有可能是subject class选错了,编辑会帮你手动选择,然后发一封邮件告知你解除……报错缺失bbl等文件,这是因为从Menu中下载的话,是没有bbl文件的。论文被on hold。

沉迷单车的追风少年 3585

Java常用类库与API的使用详解

简单来说,类库就是一组预先编写好的类的集合,这些类为我们提供了各种常用的功能。而API(Application Programming Interface,应用程序编程接口)则是类库提供的一种接口,它允许我们调用类库中的方法来实现特定的功能。通过上面的示例,我们可以看到Java的常用类库与API在编程中的重要作用。它们为我们提供了丰富的功能和便捷的操作方式,让我们能够更专注于业务逻辑的实现,而不是被底层细节所困扰。当然,Java的类库和API远不止这些,随着你学习的深入,你会发现更多有趣和实用的工具和方法。

Jz_Stu的博客 1288

【图像分类】卷积神经网络之VGGNet网络模型实现花卉图像识别(附代码和数据集,PyTorch框架)

卷积神经网络之VGGNet网络模型实现花卉图像识别(附代码和数据集,PyTorch框架)

学无止境、积少成多、厚积薄发 2430

【网络协议】【TSN】精讲TSN工作原理!图解超赞超详细!!!

TSN有一个服务等级(class of service,CoS)的概念。对TSN网络而言,不同优先级的服务对应图3中的PCP码。3位PCP码定义了0(最低)~7(最高)这8个优先级,传输类型分别对应基础、最大努力、卓越努力、严苛应用、延时和抖动小于100 ms的视频、延时和抖动小于10 ms的音频、内部网络控制、网络控制。其会对网络场景进行不同的匹配,是后续调度、配置设计中会考虑到的数据流调度因素。

风云说通信 2632

JAVA常用类的使用方法

JAVA常用类的使用方法1、Integer类2、Float类3、Double类4、Character类5、String类6、StringTokenizer类7、StringBuffer类8、Random类1.Integer类的使用方法Interger:整数类型1、属性。staticintMAX_VALUE:返回最大的整型数;staticintMIN_VALUE:返回最小的整型数;stati

syzhangzhinan的专栏 605

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

java实验7 常用类的使用

实验七 常用类的使用 实验目的 1. 了解类库的概念及API的使用方法。 2. 掌握常用类的使用方法。 实验学时 2学时 实验内容 1. 输入两个字符串str1、str2,统计字符串str2出现在str1中的次数。 如:str1=”aaas lkaaas” ,str2=” as” ,则应输出 2 提示:文本输入 import java.util.Scanner; public class test { public static void main(String[] args) { .

m0_66081324的博客 994

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Java学习笔记(常用类的概述和使用)

常用类的概述和使用常用类的概述和使用一、常用的包1、常用包的名称和功能二、简述Object类1、基本概念2、常用方法3、重写Object方法示例三、包装类 常用类的概述和使用 一、常用的包 1、常用包的名称和功能 包名 功能 包中的常用类/接口 java.lang包 Java语言的核心包,并且该包中的所有内容由Java虚拟机自动导入 System, String, Enum等 java.util包 Java语言的工具包,里面提供了大量工具类以及集合类等 Scanner, Random,

xieajiu的博客 238

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Java常用类及API的使用

API概述 概述   API(Application Programming Interface)应用程序编程接口。Java API对于程序员来说就是一本可以检索查找的字典,是JDK官方提供给程序开发者使用类的说明文档。这些类将底层的代码封装起来,我们不需要关注这些底层是如何实现的,我们只需要知道这些类是如何使用的。平常开发使用JDK类库的时候,通过查阅API的方式进行。 Scanner类 一个可以使用正则表达式来解析基本数据类型和字符串类型的简单文本扫描器。 例如:系统扫描用户输入的int类型的值 Sc

清荣峻茂的博客 318

【JAVA-CORE】常用类使用及源码解析

常用类前言面向对象相关的知识,也算正式踏入了Java开发的大门了,那么后面的课程都属于是高级部分学习了!我们会学习:常用类,集合框架,IO流,多线程,网络编程,注解和反射,以及GUI编程!其实,Java的学习,除了思想,本质还是在学习一个个类的使用!首先,我们要学习Math类,这里面有许多关于数学操作的方法,然后我们会学习时间和日期类,使用Java来获得时间相关的对象,然后会给大家讲解String类,这个我们从学java的第一天就接触的类,我们其实并未真正的了解,包括它的一些扩展StringBuilder和

我们会很适合 慢慢来 总会遇见你的 1160

java常用类的使用

常用类 内部类 #mermaid-svg-OoNP8P8WoWANfSSi .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-OoNP8P8WoWANfSSi .label text{fill:#333}#mermaid-svg-OoNP8P8WoWANfSSi .node rect,#mermaid-svg-Oo

weixin_43396669的博客 320

java之常用类的完整使用

这里写目录标题String类1.概述2、String的不可变性1、说明2.2 代码举例3、String实例化的不同方式3.1 方式说明3.2 代码举例3.3 面试题3.4 图示4. 字符串拼接方式赋值的对比4.1 说明4.2 代码举例5.常用方法6. String与其它结构的转换6.1 与基本数据类型、包装类之间的转换6.2 与字符数组之间的转换6.3 与字节数组之间的转换6.4 与StringBuffer、StringBuilder之间的转换7. JVM中字符串常量池存放位置说明:8. 常见算法题目的考查

小坏说Java,一个专注Java微服务架构的实战,Java全栈教程,SpringBoot, SpringCloud微服务到分布式、高并发架构,大数据开发,运维实战,K8S、Docker容器为一体的教程,结合企业级内部的技术栈学习 257

Java常用类使用总结

机会是留给有准备的人,大家在求职之前应该要明确自己的态度,熟悉求职流程,做好充分的准备,把一些可预见的事情做好。对于应届毕业生来说,校招更适合你们,因为绝大部分都不会有工作经验,企业也不会有工作经验的需求。同时,你也不需要伪造高大上的实战经验,以此让自己的简历能够脱颖而出,反倒会让面试官有所怀疑。你在大学时期应该明确自己的发展方向,如果你在大一就确定你以后想成为Java工程师,那就不要花太多的时间去学习其他的技术语言,高数之类的,不如好好想着如何夯实Java基础。请转发本文支持一下。

2401_84009317的博客 981

【Java基础】正则表达式的使用与常用类分享

正则表达式定义了字符串的模式。正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。

拔高、提升、创新! 1272

Java常用类及使用方法

Java常用类:String类、日期类、比较器

ggggggzzzzz的博客 1428

java常用类的方法,java常用类的使用方法

java常用类的使用方法Interger:整数类型1、属性。static int MAX_VALUE:返回最大的整型数;static int MIN_VALUE:返回最小的整型数;static Class TYPE :返回当前类型。例子:代码:System.out.println("Integer.MAX_VALUE: " + Integer.MAX_VALUE );结果为:Integer.MAX...

weixin_39996496的博客 117
上一篇: 10 大 Java 语言特性
下一篇: java基础学习:java中的反射
java_lujj
博客等级 码龄4年 18粉丝 152原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值