Java教程

Day16:JAVA反射

本文主要是介绍Day16:JAVA反射,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Day16:JAVA反射

  • 框架的底层都是注解和反射

  • 实体类:pojo、entity

  • 一个类在内存中只有一个Class对象

  • 一个类被加载后,类的整个结构都会被封装在Class对象中

  • Alt加鼠标左键可以选中不同行但同列的空间

  • 数组的类型与维度一样就是同一个Class

  • 加载-链接-初始化

  • 双亲委派机制:从上找类,找不到同名的再执行自定义类,否则不执行自定义类

注解

可以被其他程序读取(比如编译器等)

内置注解

@Override

@Deprecated

@SupperssWarnings(“”) //镇压警告

参数列表:

all:所有

unchecked:

..

元注解

负责注解其他注解

@Target(value = {ElementType.TYPE,ElementType.METHOD})

表示注解可以用在什么地方

@Retention(RetensionPolicy.RUNTIME)

SOURCE、CALSS、RUNTIME

表示在什么时候有效

@Documented

表示是否将注解生成到JAVAdoc中

@Inherited

子类可以继承父类的注解

自定义注解

@interface MyAnnotation{

//注解的参数:参数类型 + 参数名()

String name() default "";

int age() default 0;

String[] myClass() default {"嘻嘻","哈哈"};

}

参数类型只能是基本类型、Class、String、enum

default为参数值默认值

如@MyAnnotation(name = "",age=1)

注意:参数名为value时才可以省略不写

反射

主要API

java.lang.Class

java.lang.reflect.Method

java.lang.reflect.Field

java.lang.reflect.Constructor

方法

static Class forName(String name)

Object newInstance() //要获取的类必须得有一个无参构造,因为该方法调用的就是类的无参构造

getName()

getSimpleName()

Class getSuperClass()

Class[] getinterfaces()

ClassLoader getClassLoader()

Constructor[] getConstructors()

Method getMethod(String name,Class.. T) //c1.getMethod(“test”,null);c1.getMethod(“name”,String.class)

Field[] getDeclaredFields()

Method[] getMethods() //获取该类及其父类的public方法

Method[] getDeclaredMethods() //获取该类的所有方法

获取Class类的实例

  1. Test.class

  2. test.getClass()

  3. Class.forName("test.Test")

  4. 基本内置数据类型即包装类.Type,如:Integer.Type

  5. 通过ClassLoader获取

哪些类可以有Class对象

calss:外部类、成员内部类、静态内部类、局部内部类、匿名内部类

interface:接口

[]:数组

enum:枚举

annotation:注解@interface

primitive type:基本数据类型

void

类加载器

自定义类加载器 -> 系统类加载器 -> 扩展类加载器 -> 引导类加载器

以上箭头->代表其父类

自底向上检查类是否已装载 -> 自顶向下尝试加载类

ClassLoader.getSystemClassLoader()

引导类加载器

C++编写,JVM自带类加载器,负责java平台核心库,用来装载核心类库;该加载器无法直接获取

java内置类是通过引导类加载器加载的

扩展类加载器

负责jre/lib/ext目录下的jar包或 -D java.ext.dirs 指定目录下的jar包装入工作库

系统类加载器

负责java -classpath 或 -D java.class.path所指的目录下的类与jar包装入工作,是最常用的加载器

动态

Constructor类也有一个newInstance()方法 //利用这构造器创建对象

Method类有一个invoke()方法来动态调用类的方法 //m1.invoke(实例,参数)

Filed类有get/set方法来获取/设置字段值 //f1.set(实例,"test")

当涉及到操作私有的属性、构造器或方法时会报非法权限异常,但可以用f1.setAccessible(true)/m1.setAccessible(true)来避免出现这个异常

性能对比

普通方式:最快

反射方式:最慢

关闭检测方式:中

操作泛型

  • Java采用泛型擦除的机制来引入泛型,Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换问题,但是,一旦编译完成,所有和泛型有关的类型全部擦除

  • 为了通过反射操作这些类型,Java新增了ParameterizedType,GenericArrayType,TypeVariable和WildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型

  • ParameterizedType:表示一种参数化类型,比如Collection<String>

  • GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型

  • TypeVariable:是各种类型变量的公共父接口

  • WildcardType:代表一种通配符类型表达式

package test;
​
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
​
public class TestReflectGeneric {
​
    public void test01(Map<String,Test> m, List<Test> l){
        System.out.println("test01");
    }
​
    public Map<Test,String> test02(){
        System.out.println("test02");
        return null;
    }
​
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        Class c1 = Class.forName("test.TestReflectGeneric");
        Method m1 = c1.getMethod("test01", Map.class, List.class);
        Type[] genericParameterTypes = m1.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);
                }
            }
        }
​
        Method m2 = c1.getMethod("test02", null);
        Type genericReturnType = m2.getGenericReturnType();
        if(genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument);
            }
        }
​
    }
​
}

获取注解信息

ORM:Object Relationship Mapping 对象关系映射

  • 类和表结构对应

  • 属性和字段对应

  • 对象和记录对应

注解名 注解实例名 =(注解名)c1.getAnnotation(注解名.class)

注解实例名.注解属性名()获取注解属性值

 

这篇关于Day16:JAVA反射的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!