获取Class类的实例
a) 若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高
Class clazz = Person.class;
b) 若已知某个类的实例,调用该实例的getClass()方法获取Class对象
Class clazz = person.getClass();
c)已知一个类的全类名,且该类在类路径下,可以通过Class的静态方法forName()获取,可能会抛出ClassNotFoundException
Class clazz = Class.forName("com.test.Person");
d) 内置基本数据类型可以直接使用类名.Type
e) 还可以使用ClassLoader我们之后讲解
反射大致使用
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class clazz = Class.forName("org.example.reflection.User");
Constructor constructor = clazz.getDeclaredConstructor(String.class,int.class,int.class);
User user = (User)constructor.newInstance("huskyui",18,1);
System.out.println(user);
// getMethod 入参是null,并且是public
Method getName = clazz.getMethod("getName",null);
System.out.println(getName.invoke(user,null));
// setName 入参是String类型,但是是private修饰的,我们需要使用declaredMethod(),并且使用setAccessible(true)
Method method = clazz.getDeclaredMethod("setName", String.class);
method.setAccessible(true);
method.invoke(user,"adios");
System.out.println(user);
System.out.println(getName.invoke(user,null));
}
注解
// 元注解 用于修饰注解 在java.lang.annotationb包下注解
@Target
// 需要传入当前注解的,里面的值有 TYPE(class 用),FIELD(字段),METHOD.....
@Document
// 如果有这个注解,会其注释成为带注释元素的公共API的一部分
@Retention
// 指示注解要保留多长时间,默认是RetentionPolicy.ClASS,一般写是RetentionPolicy.RUNIME
@Inherited
//
举例
@Target(ElementType.FIELD)
@Retention(value= RetentionPolicy.RUNTIME)
public @interface FieldWang {
String fieldName();
String type();
int length();
String value() default "hhhh";
}
@Target(value = {ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface TableWang {
String value();
}
@TableWang("db_user")
public class User {
@FieldWang(fieldName = "user_name",type = "varchar",length = 10)
private String name;
@FieldWang(fieldName = "user_age",type = "int",length=10)
private int age;
@FieldWang(fieldName = "user_id",type = "int",length=11)
private int id;
public User(String name, int age, int id) {
this.name = name;
this.age = age;
this.id = id;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("User{");
sb.append("name='").append(name).append('\'');
sb.append(", age=").append(age);
sb.append(", id=").append(id);
sb.append('}');
return sb.toString();
}
public String getName() {
return name;
}
private void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
public static void main(String[] args) throws ClassNotFoundException {
Class clazz = Class.forName("org.example.reflection.User");
if(clazz.isAnnotationPresent(TableWang.class)){
TableWang tableWang = (TableWang) clazz.getAnnotation(TableWang.class);
System.out.println(tableWang.value());
}
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(FieldWang.class)) {
FieldWang fieldWang = (FieldWang)field.getAnnotation(FieldWang.class);
System.out.println(field.getName()+ " "+ fieldWang.fieldName() + " " + fieldWang.type() + " " + fieldWang.length());
}
}
}
// 输出
/**
db_user
name user_name varchar 10
age user_age int 10
id user_id int 11
*/
举例Mybatis中的@Select
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Repeatable(Select.List.class)
public @interface Select {
/**
* Returns an SQL for retrieving record(s).
*
* @return an SQL for retrieving record(s)
*/
String[] value();
/**
* @return A database id that correspond this statement
* @since 3.5.5
*/
String databaseId() default "";
/**
* The container annotation for {@link Select}.
* @author Kazuki Shimizu
* @since 3.5.5
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface List {
Select[] value();
}
}
@Select("select * from test where id = 1 for update")
Test selectForUpdate();
// 我们来看mybatis中的org.apache.ibatis.builder.annotation.MapperAnnotationBuilder中的方法void parseStatement(Method method)
void parseStatement(Method method) {
final Class<?> parameterTypeClass = getParameterType(method);
final LanguageDriver languageDriver = getLanguageDriver(method);
getAnnotationWrapper(method, true, statementAnnotationTypes).ifPresent(statementAnnotation -> {
// 这里获取到Annotation
final SqlSource sqlSource = buildSqlSource(statementAnnotation.getAnnotation(), parameterTypeClass, languageDriver, method);
。。。。
}
// 我们可以看到annotation.value()方法
private SqlSource buildSqlSource(Annotation annotation, Class<?> parameterType, LanguageDriver languageDriver,
Method method) {
if (annotation instanceof Select) {
return buildSqlSourceFromStrings(((Select) annotation).value(), parameterType, languageDriver);