java的注解使用
元注解
/**
** 功能描述:基础元注解
** 重点掌握 : Target Retention
** @date 2021/2/18 9:57
** @return
**/
// 表示我们的注解可以用在哪些地方
@Target(value = {ElementType.METHOD})
// 表示我们的注解在什么地方还有效
@Retention(value = RetentionPolicy.RUNTIME )
// 表示十分将我们的注解生成在JAVAdoc中
@Documented
// 表示子类可以继承父类的注解
@Inherited
public @interface Myannotation {
String valve() default "";
}
自定义注解
自定义注解的使用
@Target(value = {ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME )
@interface Myannotation {
String valve() default "";
int id() default -1;
double[] key() default {1L,2L};
}
public class MyannotationTest{
@Myannotation(valve = "test" , id = 1 , key = {3L,4L})
public void test(){
}
}
反射(Reflection)
Reflection(反射)是java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息。并能直接操作任意对象的内部属性及方法。
Class string = Class.forName('java.lang.String')
加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个歌对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,就称之为:反射
优缺点
优点:
可以实现动态创建对象和编译,体现出很大的灵活性
缺点:
对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求,这类操作总是慢于直接执行相同的操作
反射相关的主要API
java.lang.Class:代表一个类
java.lang.reflect.Method:代表类的方法
java.lang.reflect.Field:代表类的成员变量
java.lang.reflect.Constructor:代表类的构造器
…
Class类
在Object类中定义了以下的方法,此方法将被所有子类继承
public final Class getClass()
以上的方法返回值的类型是一个class类,此类是java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。
获取Class类的实例
1,已知某个类的实例,调用该实例的getClass()方法获取Class对象
Class c1 = person.getClass();
2,已知一个类的全类名,且该类在类路径下,可通过class类的静态方法forName()获取,可能抛出ClassNotFoundException
Class c2 = Class.forName("com.xiaojun.crm.Reflect.Stubent");
3,若已知具体的类,通过累的class属性获取,该方法最为安全可靠,程序性能最高。
Class c3 = Stubent.class;
4,内置基本数据类型可以直接用类名.TYPE
Class c4 = Integer.TYPE;
5,还可以利用ClassLoader
package com.xiaojun.crm.Reflect;
public class Test02 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Person();
System.out.println(person.name);
// 方式一:通过对象获得
Class c1 = person.getClass();
System.out.println(c1.hashCode());
// 方式二:forname获得
Class c2 = Class.forName("com.xiaojun.crm.Reflect.Stubent");
System.out.println(c2.hashCode());
// 方式三:通过类名,class获得
Class c3 = Stubent.class;
System.out.println(c3.hashCode());
// 方式四:基本内置类型的包装类都有一个Type属性
Class c4 = Integer.TYPE;
System.out.println(c4);
// 获取父类类型
Class c5 = c1.getSuperclass();
System.out.println(c5);
}
}
class Person{
String name;
public Person(String name) {
this.name = name;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Stubent extends Person{
public Stubent() {
this.name = "学生";
}
}
class Teacherr extends Person{
public Teacherr() {
this.name = "老师";
}
}
所有对象的class对象
Class c1 = Object.class; // 类
Class c2 = Comparable.class; //接口
Class c3 = String[].class; // 一维数组
Class c4 = int[][].class; // 二维数组
Class c5 = Override.class; // 注解
Class c6 = ElementType.class; // 枚举
Class c7 = Integer.class; // 基本数据类型
Class c8 = void.class; // void
Class c9 = Class.class; // Class
System.out.println(c1); //class java.lang.Object
System.out.println(c2); //interface java.lang.Comparable
System.out.println(c3); //class [Ljava.lang.String;
System.out.println(c4); //class [[I
System.out.println(c5); //interface java.lang.Override
System.out.println(c6); //class java.lang.annotation.ElementType
System.out.println(c7); //class java.lang.Integer
System.out.println(c8); //void
System.out.println(c9); //class java.lang.Class
通过反射,动态创建对象
// 获得class对象
Class c1 = Class.forName("com.xiaojun.crm.Reflect.User");
// 构造一个对象
User user = (User)c1.newInstance();//本质是调用了类的无参构造器
System.out.println(user);
// 通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, String.class);
User user2 = (User)constructor.newInstance("王一", 18, "男");
System.out.println(user2);
// 通过反射调用普通方法
User user3 = (User)c1.newInstance();
// 通过反射获取一个方法
Method setName = c1.getDeclaredMethod("setName", String.class);
// invoke:激活
// (对象,"方法的值")
setName.invoke(user3,"王三");
System.out.println(user3.getName());
System.out.println("=========================");
User user4 = (User)c1.newInstance();
Field name = c1.getDeclaredField("name");
// 不能直接操作私有属性,我们需关闭程序的安全检测,属性或者方法的setAccessible(true);
name.setAccessible(true);
name.set(user4,"王四");
System.out.println(user4.getName());
反射操作泛型
java采用泛型擦除的机制来引入泛型,java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换问题,但是,一旦编译完成,所有和泛型有关的类型全部擦除
为了通过反射操作这些类型,java新增了ParameterizedType,GenericArrayType,TypeVariable和WildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型
1,ParameterizedType:表示一种参数化类型,比如Collection
2,GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型
3,TypeVariable:是各种类型变量的公共父接口
4,WildcardType:代表一种通配符类型表达式
public class Test04 {
public void test01(Map<String,User> map, List<User> list){
System.out.println("test01");
}
public Map<String,User> test02(){
System.out.println("test02");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = Test04.class.getMethod("test01", Map.class, List.class);
// 获取泛型
Type[] genericParameterTypes = method.getGenericParameterTypes();
for ( Type genericParameterType : genericParameterTypes ) {
System.out.println("##:"+genericParameterType);
if (genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for ( Type actualTypeArgument : actualTypeArguments ) {
System.out.println(actualTypeArgument);
}
}
}
System.out.println("==============================");
method = Test04.class.getMethod("test02",null);
// 获取泛型
Type genericReturnType = method.getGenericReturnType();
System.out.println("##:"+genericReturnType);
if (genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for ( Type actualTypeArgument : actualTypeArguments ) {
System.out.println(actualTypeArgument);
}
}
}
}
通过反射获取注解信息
public class AnnoAndReflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.xiaojun.crm.Reflect.User2");
// 通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for ( Annotation annotation : annotations ) {
System.out.println(annotation);
}
Table table = (Table)c1.getAnnotation(Table.class);
String value = table.value();
System.out.println(value);
// 获取类属性指定的注解
Field field = c1.getDeclaredField("name");
FiledCustomize annotation = field.getAnnotation(FiledCustomize.class);
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}
}
@Table("db_user2")
class User2{
@FiledCustomize(columnName = "db_id", type = "int", length = 10)
private int id;
@FiledCustomize(columnName = "db_age", type = "int", length = 10)
private int age;
@FiledCustomize(columnName = "db_name", type = "varchar", length = 6)
private String name;
public User2() {
}
public User2(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User2{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
// 类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
String value();
}
// 属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FiledCustomize{
String columnName();
String type();
int length();
}