这篇注解与反射文章是基于 狂神说哔站视频的笔记与总结,仅供个人学习和复习用。欲学习知识推荐前往大佬的博客中学习。
注解 Annotation
Annotation的作用
- 不是程序本身,可以对程序作出解释。
- 可以被其他程序(编译器等)读取。
Annotation的格式:
- 注解是以”@注释名”在代码中存在的,还可以增加一些参数值。例如:@SuppressWarnings(Value=”unchecked”)
元注解
@MyAnnotation
public class Test01 {
}
/**定义一个注解
* @Target : 表示我们的注解可以用到什么地方
* @Retention : 表示我们的注解在什么地方还有效 runtime > class > sources
*/
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
@Documented //表示是否将我们的注解生成在JAVAdoc中
@Inherited //子类可以继承父类的注解
@interface MyAnnotation{
}
反射 Reflection
Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能操作任意对象的内部属性及方法。
获取Class类的方式
public class demo2 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
System.out.println(person.name);
//通过反射获取类的的Class对象
//方式一 :通过对象获得
Class c1 = person.getClass();
System.out.println(c1.hashCode());
//方式二 :forname获得
Class c2 = Class.forName("com.kuang.demo2.Student");
System.out.println(c2.hashCode());
//方式三 :通过类名.class获得
Class c3 = Student.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{
public String name;
}
class Teacher extends Person{
public Teacher() {
this.name = "老师";
}
}
class Student extends Person{
public Student() {
this.name = "学生";
}
}
通过反射获取类中的内容
- 实体类
//实体类
class Person{
public String name;
}
class Teacher extends Person{
public Teacher() {
this.name = "老师";
}
}
class Student extends Person{
private String address;
public int id;
public Student() {
this.name = "学生";
}
public Student(String address, int id) {
this.address = address;
this.id = id;
}
public void test(){
System.out.println("测试*********");
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Student{" +
"address='" + address + '\'' +
", id=" + id +
'}';
}
}
- 反射操作
public class demo03 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("com.kuang.demo2.Student");
//获取类的名字
System.out.println(c1.getName());
System.out.println(c1.getSimpleName());
//获得类的属性
System.out.println("**********************");
//Field[] fields = c1.getFields(); //获得所有public属性包括父类中的字段
Field[] fields = c1.getDeclaredFields();//获得某个类的声明字段,既包括public private 和proteced,但是不包括父类的声明字段
for (Field field : fields) {
System.out.println(field);
}
//获得指定属性的值
System.out.println("********************");
Field address = c1.getDeclaredField("address");//获得当前类的指定属性 不包括父类的
System.out.println(address);
//获得类的方法
System.out.println("********************");
// Method[] methods = c1.getMethods(); //获得本类及其父类的全部public方法
// for (Method method : methods) {
// System.out.println("正常的:"+method);
// }
Method[] methods = c1.getDeclaredMethods(); //获得本类的所有方法
for (Method method : methods) {
System.out.println("getDeclaredMethods" + method);
}
//获得指定方法
//重载
Method getAddress = c1.getMethod("getAddress", null);
Method setAddress = c1.getMethod("setAddress", String.class);
System.out.println(getAddress);
System.out.println(setAddress);
//获得指定构造器
System.out.println("*************");
Constructor[] constructors = c1.getConstructors();//只返回制定参数类型访问权限是public的构造器。
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
Constructor[] declaredConstructors = c1.getDeclaredConstructors();//返回制定参数类型的所有构造器,包括public的和非public的,当然也包括private的。
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
//获得指定的构造器
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class);
System.out.println(declaredConstructor);
}
}
结果
com.kuang.demo2.Student
Student
**********************
private java.lang.String com.kuang.demo2.Student.address
public int com.kuang.demo2.Student.id
********************
private java.lang.String com.kuang.demo2.Student.address
********************
getDeclaredMethodspublic java.lang.String com.kuang.demo2.Student.getAddress()
getDeclaredMethodspublic void com.kuang.demo2.Student.test()
getDeclaredMethodspublic void com.kuang.demo2.Student.setAddress(java.lang.String)
public java.lang.String com.kuang.demo2.Student.getAddress()
public void com.kuang.demo2.Student.setAddress(java.lang.String)
*************
public com.kuang.demo2.Student()
public com.kuang.demo2.Student(java.lang.String,int)
public com.kuang.demo2.Student()
public com.kuang.demo2.Student(java.lang.String,int)
public com.kuang.demo2.Student(java.lang.String,int)
通过反射动态的创建对象
- 实体类
//实体类
class Person{
public String name;
}
class Teacher extends Person{
public Teacher() {
this.name = "老师";
}
}
class Student extends Person{
private String address;
public int id;
public Student() {
this.name = "学生";
}
public Student(String address, int id) {
this.address = address;
this.id = id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Student{" +
"address='" + address + '\'' +
", id=" + id +
'}';
}
}
- 反射操作
//通过反射动态的创建对象
public class demo04 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获得Class对象
Class c1 = Class.forName("com.kuang.demo2.Student");
//构造一个对象
Student st = (Student) c1.newInstance(); //本质是调用了类的无参构造器
System.out.println(st);
//通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class);
Student st2 = (Student) constructor.newInstance("广州", 1);
System.out.println(st2);
//通过反射调用普通方法
Student st3 = (Student) c1.newInstance();//构造一个对象
//通过反射获取一个方法
Method setAddress = c1.getDeclaredMethod("setAddress", String.class);
setAddress.invoke(st3,"广州"); //invoke:激活的意思 (对象,"方法的值")
System.out.println(st3.getAddress());
//通过反射操作属性
System.out.println("*********************");
Student st4 = (Student) c1.newInstance();//构造一个对象
Field address = c1.getDeclaredField("address");//反射获取属性
address.setAccessible(true);//不能直接操作私有属性,我们需要关闭程序的安全检测,属性或者方法的setAccessible(true)
address.set(st4,"广州");
System.out.println(st4.getAddress());
Field id = c1.getDeclaredField("id");
id.set(st4,1);//id为public 属性可以直接操作
System.out.println(st4.getId());
}
}
- 打印结果
Student{address='null', id=0}
Student{address='广州', id=1}
广州
*********************
广州
1
分析性能问题
- 实体类
//实体类
class Person{
public String name;
}
class Teacher extends Person{
public Teacher() {
this.name = "老师";
}
}
class Student extends Person{
private String address;
public int id;
public Student() {
this.name = "学生";
}
public Student(String address, int id) {
this.address = address;
this.id = id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Student{" +
"address='" + address + '\'' +
", id=" + id +
'}';
}
}
- 测试类
//性能对比
public class demo05 {
//普通方式调用
public static void test01(){
Student student = new Student();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
student.getAddress();
}
long endTime = System.currentTimeMillis();
System.out.println("普通方式执行:"+(endTime-startTime)+"ms");
}
//反射方式调用
public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Student student2 = new Student();
Class c1 = student2.getClass();
Method setId = c1.getDeclaredMethod("setId", int.class);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
setId.invoke(student2,111);
}
long endTime = System.currentTimeMillis();
System.out.println("反射方式执行:"+(endTime-startTime)+"ms");
}
//反射方式调用 关闭检测
public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Student student3 = new Student();
Class c2 = student3.getClass();
Method setId = c2.getDeclaredMethod("setId", int.class);
setId.setAccessible(true);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
setId.invoke(student3,111);
}
long endTime = System.currentTimeMillis();
System.out.println("关闭检测后反射方式执行:"+(endTime-startTime)+"ms");
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
test01();
test02();
test03();
}
}
- 结果
普通方式执行:0ms
反射方式执行:46ms
关闭检测后反射方式执行:34ms
通过反射获取泛型
public class demo07 {
public void test01(Map<String,Student> map, List<Student> list){
System.out.println("test01");
}
public Map<String,Student> test02(){
System.out.println("test02");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = demo07.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);
}
}
}
Method method2 = demo07.class.getMethod("test02",null);
Type genericReturnType = method2.getGenericReturnType();
if(genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("return" + actualTypeArgument);
}
}
}
}
***java.util.Map<java.lang.String, com.kuang.demo2.Student>
class java.lang.String
class com.kuang.demo2.Student
***java.util.List<com.kuang.demo2.Student>
class com.kuang.demo2.Student
returnclass java.lang.String
returnclass com.kuang.demo2.Student
通过反射获取注解信息
//反射操作注解
public class demo08 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.kuang.demo2.Student2");
//通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//获得注解的value的值
TableStudent tableStudent = (TableStudent)c1.getAnnotation(TableStudent.class);
String value = tableStudent.value();
System.out.println(value);
//获得类指定的注解
Field f = c1.getDeclaredField("name");
FieldStudent annotation = f.getAnnotation(FieldStudent.class);
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}
}
@TableStudent("db_student")
class Student2{
@FieldStudent(columnName = "db_id",type = "int",length = 10)
private int id;
@FieldStudent(columnName = "db_age",type = "int",length = 10)
private int age;
@FieldStudent(columnName = "db_name",type = "varchar",length = 3)
private String name;
public Student2() {
}
public Student2(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 "Student2{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableStudent{
String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldStudent{
String columnName();
String type();
int length();
}
结果
@com.kuang.demo2.TableStudent(value=db_student)
db_student
db_name
varchar
3