Stream + 并行流 +Optional +接口的方法 +日期组件+重复注解及类型注解

Stream + 并行流 +Optional +接口的方法 +日期组件+重复注解及类型注解

一、Stream流

1.终止操作 - 归约

归约:将流中的元素反复结合起来,得到一个值

map+reduce的连接通常称为map_reduce模式,因Google用它进行网络搜索而出名

方法描述
reduce( T identity , BinaryOperator accumulator)参数:(初始值,结合逻辑)
reduce(BinaryOperator accumulator)参数:(结合逻辑)
public class Student implements Comparable<Student>{

	private String name;
	private int age;
	private double salary;
	private Course course;
	
	public Student() {
	}
	
	public Student(String name, int age, double salary, Course course) {
		this.name = name;
		this.age = age;
		this.salary = salary;
		this.course = course;
	}



	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public Course getCourse() {
		return course;
	}

	public void setCourse(Course course) {
		this.course = course;
	}
	
	

	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", salary=" + salary + ", course=" + course + "]";
	}

	@Override
	public int hashCode(){
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((course == null) ? 0 : course.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		long temp;
		temp = Double.doubleToLongBits(salary);
		result = prime * result + (int)(temp ^ (temp >>> 32) );
		return result;
	}
	
	@Override
	public boolean equals(Object obj) {
		if(this == obj)
			return true;
		if(obj == null)
			return false;
		if(getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if(age != other.age)
			return false;
		if(course != other.course)
			return false;
		if (name == null) {
			if (other.name != null) 
				return false;
		} else if(!name.equals(other.name))
			return false;
		if(Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
			return false;
		return true;
	}
	@Override
	public int compareTo(Student o) {
		if(this == o){
			return 0;
		}
		if (this.age != o.age) {
			return Integer.compare(this.age, o.age);
		}
		return 1;
	}

}
public enum Course {

	JAVA,HTML,PYTHON;
}

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

import org.junit.Test;

public class Test01 {

	List<Integer> numList = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
	List<Student> stuList = Arrays.asList(
			new Student("张三", 28, 4800,Course.JAVA),
			new Student("李四", 36, 7200,Course.JAVA),
			new Student("王五", 19, 9600,Course.HTML),
			new Student("赵六", 42, 6100,Course.HTML),
			new Student("孙七", 23, 9600,Course.PYTHON),
			new Student("吴八", 31, 3000,Course.PYTHON),
			new Student("李四", 36, 7200,Course.JAVA));
	
	@Test
	public void test01(){
		//需求:获取numList集合中元素的总和
		Integer reduce = numList.stream().reduce(0, (x,y)->x+y);
		System.out.println(reduce);
		
	}
	
	@Test
	public void test02(){
		//需求:获取stuList集合中所有学生工资总和
		Optional<Double> reduce = stuList.stream().map(Student::getSalary).reduce((salary1,salary2)->salary1+salary2);
		Double sum = reduce.get();
		System.out.println(sum);
		
	}
}

2.终止操作 - 收集

收集:将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法

方法描述
collect(Collector<? super T, A, R> collector)把元素放入Collector集合中
import java.util.ArrayList;
import java.util.Arrays;
import java.util.DoubleSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import org.junit.Test;

public class Test02 {
	List<Student> stuList = Arrays.asList(
			new Student("张三", 28, 4800,Course.JAVA),
			new Student("李四", 36, 7200,Course.JAVA),
			new Student("王五", 19, 9600,Course.HTML),
			new Student("赵六", 42, 6100,Course.HTML),
			new Student("孙七", 23, 9600,Course.PYTHON),
			new Student("吴八", 31, 3000,Course.PYTHON),
			new Student("李四", 36, 7200,Course.JAVA));
	
	@Test
	public void test01(){
		//需求1:把当前学生姓名提取出来,并把数据放入List集合中
		List<String> list = stuList.stream().map((stu)->stu.getName()).collect(Collectors.toList());
		for (String name : list) {
			System.out.println(name);
		}
	}
	
	@Test
	public void test02(){
		//需求2:把当前学生姓名提取出来,并把数据放入Set集合中
		Set<String> set = stuList.stream().map((stu)->stu.getName()).collect(Collectors.toSet());
		for (String name : set) {
			System.out.println(name);
		}
	}
	
	@Test
	public void test03(){
		//需求3:把当前学生姓名提取出来,并把数据放入指定集合中
		ArrayList<String> arrayList = stuList.stream().map((stu)->stu.getName()).collect(Collectors.toCollection(ArrayList::new));
		for (String name : arrayList) {
			System.out.println(name);
		}
	}
	
	@Test
	public void test04(){
		//需求4:收集/获取学生个数
		Long count = stuList.stream().collect(Collectors.counting());
		System.out.println(count);
	}
	
	@Test
	public void test05(){
		//需求5:收集/获取学生平均工资
		Double avg = stuList.stream().collect(Collectors.averagingDouble(Student::getSalary));
		System.out.println(avg);
	}
	
	@Test
	public void test06(){
		//需求6:收集/获取学生总工资
		 Double sum = stuList.stream().collect(Collectors.summingDouble(Student::getSalary));
		 System.out.println(sum);
	}
	
	@Test
	public void test07(){
		//需求7:收集/获取学生工资最大值
		Optional<Double> maxOptional = stuList.stream().map((stu)->stu.getSalary()).collect(Collectors.maxBy(Double::compareTo));
		Double max = maxOptional.get();
		System.out.println(max);
	}
	
	@Test
	public void test08(){
		//需求8:收集/获取学生工资最大值
		Optional<Double> minOptional = stuList.stream().map((stu)->stu.getSalary()).collect(Collectors.minBy(Double::compareTo));
		Double min = minOptional.get();
		System.out.println(min);
	}
	
	@Test
	public void test09(){
		//需求9:收集/获取工资最多的学生信息
		Optional<Student> stuOptional = stuList.stream().collect(Collectors.maxBy(
				(stu1,stu2)->Double.compare(stu1.getSalary(), stu2.getSalary())));
		Student stu = stuOptional.get();
		System.out.println(stu);
	}
	
	@Test
	public void test10(){
		//需求10:收集/获取工资最少的学生信息
		Optional<Student> stuOptional = stuList.stream().collect(Collectors.minBy(
				(stu1,stu2)->Double.compare(stu1.getSalary(), stu2.getSalary())));
		Student stu = stuOptional.get();
		System.out.println(stu);
	}
	
	@Test
	public void test11(){
		//需求11:按照学科分组
		Map<Course, List<Student>> map = stuList.stream().collect(Collectors.groupingBy(Student::getCourse));
		Set<Entry<Course,List<Student>>> entrySet = map.entrySet();
		for (Entry<Course, List<Student>> entry : entrySet) {
			System.out.println(entry);
		}
	}
	
	@Test
	public void test12(){
		//需求12:按照学科分组,在按照年龄分组
		Map<Course, Map<String, List<Student>>> map = stuList.stream().collect(Collectors.groupingBy(Student::getCourse,Collectors.groupingBy((obj)->{
			Student stu = (Student)obj;
			int age = stu.getAge();
			if(age<28){
				return "青年";
			}
			if(age<40){
				return "中年";
			}
			return "老年";
		})));
		Set<Entry<Course,Map<String,List<Student>>>> entrySet = map.entrySet();
		for (Entry<Course, Map<String, List<Student>>> entry : entrySet) {
			Course key = entry.getKey();
			Map<String, List<Student>> value = entry.getValue();
			System.out.println(key + " -- " + value);
		}
	}
	
	@Test
	public void test13(){
		//需求13:按照工资5000为标准分区
		Map<Boolean, List<Student>> map = stuList.stream().collect(Collectors.partitioningBy((stu)->{
			if(stu.getSalary() > 5000){
				return true;
			}
			return false;
		}));
		Set<Entry<Boolean,List<Student>>> entrySet = map.entrySet();
		for (Entry<Boolean, List<Student>> entry : entrySet) {
			System.out.println(entry);
		}
		
	}
	
	@Test
	public void test14(){
		//需求14:获取学生工资信息,再获取总值、平均值、最大值、最小值
		
		//DoubleSummaryStatistics对象 -- 学生工资信息
		DoubleSummaryStatistics collect = stuList.stream().collect(Collectors.summarizingDouble(Student::getSalary));
	
		double sum = collect.getSum();
		double avg = collect.getAverage();
		double max = collect.getMax();
		double min = collect.getMin();
		System.out.println(sum);
		System.out.println(avg);
		System.out.println(sum);
		System.out.println(max);
		System.out.println(min);
	}
	
	@Test
	public void test15(){
		//需求15:拼接学生姓名
		
		String str1 = stuList.stream().map(Student::getName).collect(Collectors.joining());
		System.out.println(str1);
		
		String str2= stuList.stream().map(Student::getName).collect(Collectors.joining(","));
		System.out.println(str2);
		
		String str3= stuList.stream().map(Student::getName).collect(Collectors.joining(",", "-", "-"));
		System.out.println(str3);
	}
}

二、并行流与串行流

并行流就是把一个内容拆分成多个数据块,并用不同的线程分别处理每个数据块的流。Java8中将并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API可以声明性地通过 parallel() - 并行流 与sequential()-顺序流 之间进行切换。

注意

  1. 默认为顺序流/串行流
  2. 并行流一般在大数据搜索里使用到
  3. JDK1.8之前也有并行流,叫做Fork/Join并行计算框架
import java.util.stream.LongStream;

public class Test03 {	
	public static void main(String[] args) {
		
		//需求:计算1-10000000L之和
		
		long sum = LongStream.range(1, 10000000L).//获取Stream流对象,该对象中存储了1~10000000L的数字
				parallel().//设置该流为并行流(底层会给我们拆分成多个线程去计算)
				reduce(0, (x,y)->x+y);//归约
		System.out.println(sum);
	}
}

三、Optional

Optional类(java. util. Optional)是一个容器类,代表一个存在或不存在的值,原来用null表示一个值不存在,现在Optional可以更好的表达这个概念。并且可以避免空指针异常

此类的设计就是更好的避免空指针异常

方法描述
Optional.of(T t)创建一个Optional实例
Optional.empty()创建一 个空的 Optional实例
Optional.ofNullable(T t)若t不为null,创建Optional实例,否则创建空实例
get()获取Optional实例里的对象
isPresent()判断是否包含值
orElse(T t)如果调用对象包含值, 返回该值,否则返回t
orElseGet(Supplier s)如果调用对象包含值,返回该值,否则返回s获取的值
map(Function f)如果有值对其处理,并返回处理后的Optional,否则返回optional. empty()
flatMap(Function mapper)与map 类似,要求返回值必须是Optional
import java.util.Optional;

import com.qf.stream.Student;

public class Test01 {

	public static void main(String[] args) {
		//获取Optional的对象,该对象中存储了一个学生对象
//		Optional<Student> optional = Optional.of(new Student());
	
		//获取Optional对象中的学生对象
//		Student stu = optional.get();
//		System.out.println(stu);
		
		//创建Optional的对象,该对象中没有存储了学生对象
		Optional<Object> optional = Optional.empty();
		
		//获取Optional对象中的学生对象,但是Optional对象中没有学生对象,就创建个学生对象(最大化限度的减少了空指针异常)
		Object stu = optional.orElse(new Student());
		System.out.println(stu);
        
        //不同情况下可以返回不同对象,orElseGet()比orElse()可变性更强
		boolean bool = true;
		stu = op.orElseGet(()->{
			if(bool){
				return new Student("刘备", 26, 8888, Course.JAVA);
			}else{
				return new Student("甘夫人", 26, 8888, Course.JAVA);
			}
		});
		
		//获取原容器中的某个值并返回新容器中
		//map(Function<? super T, ? extends U> mapper)
		Optional<String> map = op.map(Student::getName);
		System.out.println(map.get());
		
		//与map 类似,要求返回值必须是Optional
		//flatMap(Function<? super T, Optional<U>> mapper)
		Optional<String> flatMap = op.flatMap((e)->Optional.of(e.getName()));
		System.out.println(flatMap.get());
	}
}

四、接口的默认方法与静态方法

从JDK1.8开始,接口中可以有默认方法,既default修饰的方法,此方法可以让接口的实现类所调用,而接口中的静态方法直接用接口名调用即可

接口默认方法的”类优先”原则:

如果一个接口中定义了一个默认方法,而接口实现类的父类定义了一个同名的方法时,选择父类中的方法

public class Test01 {

	public static void main(String[] args) {
		
		B b = new B();
		b.method();
	}
}

class A{
	public void method(){
		System.out.println("父类中的method方法");
	}
}

class B extends A implements I1{}
interface I1{
	default void method(){
		System.out.println("接口中的默认方法");
	}
}

接口冲突:如果一个父接口提供一个默认方法,而另一个接口也提供了一个具有相同名称和参数列表的方法(不管方法是否是默认方法),那么必须覆盖该方法来解决冲突

public class Test01 {

	public static void main(String[] args) {
		
	}
}

interface I1{
	default void method(){
		System.out.println("I1接口中的默认方法");
	}
}

interface I2 extends I1{
	public void method();
}

class A implements I1,I2{
	
	@Override
	public void method() {
	}
}

五、日期组件

JDK1.8提供的新日期类都是不可变的,既不管怎么样的改变,都会产生一个新的实例,他们都是线程安全的

日期组件遵循与IOS-8601世界时间标准

1.组件简介

包路径类名描述
java.time针对日期和时间操作的包
LocalDate用于表示日期的类
LocalTime用于表示时间的类
LocalDateTime用于表示日期时间的类
Instant时间戳类(1970.1.1 0:0:0 到现在的毫秒数
Period两个日期间隔类
Duration两个时间间隔类
java.time.chrono针对日期时间特殊格式操作的包
java.time.format针对时间日期时间格式化操作的包
DateTimeFormatter格式化日期时间类
java.time.temporal针对时间矫正操作的包
java.time.zone针对时区操作的包

2.日期时间类、时间戳、间隔类

import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.Period;
import java.time.ZoneOffset;

import org.junit.Test;

public class Test01 {

	@Test
	public void test01(){
		//LocalDate LocalTime LocalDateTime
		//这三个日期类的使用大致一样

		//获取当前日期时间对象
		LocalDateTime ldt1 = LocalDateTime.now();
		System.out.println(ldt1);//2022-10-31T11:23:18:102

		//获取指定日期时间对象
		LocalDateTime ldt2 = LocalDateTime.of(2020, 1, 23, 8, 30, 10, 10);
		System.out.println(ldt2);//2020-1-23T8:30:10:10

		//获取ldt1推后的时间日期对象
		LocalDateTime ldt3 = ldt1.plusYears(2);//退后两年
		System.out.println(ldt3);2024-10-31T11:23:18:102

		//获取ldt1提前的时间日期对象
		LocalDateTime ldt4 = ldt3.minusMonths(2);//提前两个月
		System.out.println(ldt4);//2024-8-31T11:23:18:102

		//获取日期中的单个信息
		System.out.println(ldt4.getYear());
		System.out.println(ldt4.getMonthValue());
		System.out.println(ldt4.getDayOfMonth());
		System.out.println(ldt4.getHour());
		System.out.println(ldt4.getMinute());
		System.out.println(ldt4.getSecond());
	}

	@Test
	public void test02(){
		//使用时间戳(从1970年1月1日0:0:0到现在的毫秒值)

		//默认创建UTC(世界标准时间)时区的时间戳对象
		Instant now1 = Instant.now();
		System.out.println(now1);//2022-10-31T03:27:55.921Z

		//获取偏移8小时的偏移日期时间对象
		OffsetDateTime odt = now1.atOffset(ZoneOffset.ofHours(8));
		System.out.println(odt);//2022-10-31T11:27:55.921+08:00

		//获取时间戳的毫秒值形式
		System.out.println(now1.toEpochMilli());

		//获取一个1970年1月1日0:0:0 往后退1秒的时间戳对象
		Instant now2 = Instant.ofEpochSecond(1);
		System.out.println(now2);
	}

	@Test
	public void test03() throws InterruptedException {
		//Duration:时间间隔类

		Instant now1 = Instant.now();
		Thread.sleep(1000);
		Instant now2 = Instant.now();

		//获取时间间隔类对象
		Duration duration1 = Duration.between(now1, now2);
		System.out.println(duration1.toMillis());

		System.out.println("-----------------------------");

		LocalTime lt1 = LocalTime.now();
		Thread.sleep(1000);
		LocalTime lt2 = LocalTime.now();
		//获取时间间隔类对象
		Duration duration2 = Duration.between(lt1, lt2);
		System.out.println(duration2.toMillis());
	}	
	@Test
	public void test04() throws InterruptedException {
		//Period:日期间隔类
		LocalDate ld1 = LocalDate.of(2021, 12, 28);
		Thread.sleep(1000);
		LocalDate ld2 = LocalDate.of(2022, 10, 31);

		//获取日期间隔类对象
		Period period = Period.between(ld1, ld2);

		System.out.println(period.getYears());//0
		System.out.println(period.getMonths());//10
		System.out.println(period.getDays());//3
	}
}

3.日期时间格式化类-DateTimeFormatter

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import org.junit.Test;

public class Test02 {

	@Test
	public void test01() {
		//格式化日期时间类
		LocalDateTime ldt1 = LocalDateTime.now();//2022-10-31T11:35:18:122
		
		//获取本地标准的日期时间格式化对象
		DateTimeFormatter dtf1 = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
		String strDateTime1 = ldt1.format(dtf1);//格式化时间日期
		System.out.println(strDateTime1);//2022-10-31T11:35:18:122
		
		//自定义日期时间格式化对象
		DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
		String strDateTime2 = ldt1.format(dtf2);//格式化时间日期
		System.out.println(strDateTime2);
		
		//将指定格式的字符串解析成LocalDateTime对象
		LocalDateTime parse = LocalDateTime.parse("2020年03月12日 11:04:14", dtf2);
		System.out.println(parse);
	}
}

4.时间矫正器类-TemporalAdjuster

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;

import org.junit.Test;

public class Test04 {

	@Test
	public void test01() {
		//时间矫正器
		LocalDateTime ldt1 = LocalDateTime.now();//2022-10-31T14:03:18:122

		//设置指定月份
		LocalDateTime ldt2 = ldt1.withMonth(12);
		System.out.println(ldt2);//2022-12-31T14:03:18:122

		//设置下一个周末
		LocalDateTime ldt3 = ldt1.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
		System.out.println(ldt3);

		//自定义时间矫正器:设置下一个工作日
		LocalDateTime ldt4 = ldt1.with((temporal)->{
			//获取到日期时间对象
			LocalDateTime ldt = (LocalDateTime) temporal;
			//获取周几?
			DayOfWeek week = ldt.getDayOfWeek();
			if(week.equals(DayOfWeek.FRIDAY)){//周五
				return ldt.plusDays(3);//往后推3天
			}else if(week.equals(DayOfWeek.SATURDAY)){//周六
				return ldt.plusDays(2);//往后推2天
			}else{
				return ldt.plusDays(1);//往后推1天
			}
		});
		System.out.println(ldt4);
	}
}

5.时区类

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Set;

import org.junit.Test;

public class Test03 {

	@Test
	public void test01() {
		//时区类 

		//获取所有时区字符串
		Set<String> set = ZoneId.getAvailableZoneIds();
		for (String str : set) {
			System.out.println(str);
		}
		
		System.out.println("-------------");
		
		//获取指定时区的日期时间对象
		LocalDateTime ldt1 = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));
		System.out.println(ldt1);
		
		//获取指定时区的日期时间对象 + 偏移量
		LocalDateTime ldt2 = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));
		ZonedDateTime zonedDateTime = ldt2.atZone(ZoneId.of("Asia/Tokyo"));
		System.out.println(zonedDateTime);
	}
}

6.传统日期格式化的线程问题

需求:让多线程同时去解析日期

1.使用JDK1.7时的日期时间类会出现问题

错误示范

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Test01 {
	public static void main(String[] args) throws Exception {
		
		//创建日期格式化类的对象	
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		
		//创建带有返回值的任务类的对象
		Callable<Date> task = new Callable<Date>() {
			@Override
			public Date call() throws Exception {
				Date date = sdf.parse("20200123");
				return date;
			}
		};
		
		//创建线程池
		ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
		
		//提交任务
		ArrayList<Future<Date>> list = new ArrayList<>();
		for (int i = 1; i <= 10; i++) {
			Future<Date> future = pool.submit(task);
			list.add(future);
		}
		
		//遍历集合
		for (Future<Date> future : list) {
			Date date = future.get();
			System.out.println(date);
		}
		
		//关闭线程池
		pool.shutdown();
	}
}
2.使用JDK1.8的日期时间类

正确示范

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Test02 {
	public static void main(String[] args) throws Exception {
		
		//创建日期格式化类的对象	
		DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
		
		//创建带有返回值的任务类的对象
		Callable<LocalDate> task = new Callable<LocalDate>() {
			@Override
			public LocalDate call() throws Exception {
				
				LocalDate localDate = LocalDate.parse("20200123", dtf);
				return localDate;
			}
		};
		
		//创建线程池
		ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
		
		//提交任务
		ArrayList<Future<LocalDate>> list = new ArrayList<>();
		for (int i = 1; i <= 10; i++) {
			Future<LocalDate> future = pool.submit(task);
			list.add(future);
		}
		
		//遍历集合
		for (Future<LocalDate> future : list) {
			LocalDate date = future.get();
			System.out.println(date);
		}
		
		//关闭线程池
		pool.shutdown();
	}
}

六、重复注解及类型注解

jdk1.8开始可以重复注解

ps:一个类可有多个同样的注解

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

@Author(name="G")
@Author(name="Z")
public class Test01 <@Author(name="L") T>{

	public static void main(String[] args) throws Exception {
		
		Class<?> clazz = Test01.class;
		
		//利用反射获取类上的重复注解
		Author[] typeAuthors = clazz.getAnnotationsByType(Author.class);
		for (Author author : typeAuthors) {
			String name = author.name();
			System.out.println(name);
		}
		
		//利用反射获取方法中参数上的注解
		Method method = clazz.getDeclaredMethod("method", String.class);
		Parameter[] parameters = method.getParameters();//获取方法上的参数对象
		for (Parameter parameter : parameters) {
			//获取参数上的重复注解
			Author[] parameterAuthors = parameter.getAnnotationsByType(Author.class);
			for (Author author : parameterAuthors) {
				String name = author.name();
				System.out.println(name);
			}
			
			//获取参数类型
			Class<?> type = parameter.getType();
			System.out.println(type);
			//获取参数名(参数名不会编译到class文件)
			String name = parameter.getName();
			System.out.println(name);
			
		}
	}
	public void method(@Author(name="GL") @Author(name="ZL")String xxx){}
}
//作者注解
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Repeatable(Authors.class)
@Target({TYPE,PARAMETER,TYPE_PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Author {
	
	String name();
}
//作者注解的容器
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({TYPE,PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Authors {

	Author[] value();
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨霖先森

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值