Java注解和反射的学习一

spider   ·   发表于 2023-06-07 08:58:31   ·   技术文章

前言:

首先讲解何为反射:
例如外挂:在程序正在跑的时候 加入一段代码,就可以实现得到一些东西,那么这个就是HOOK钩子注入
其实外挂就是这个过程,例如,打开游戏的时候正在运行的时候,这个时候打开外挂,就可以用锁血什么的。这其实就有点类似于这个了,专业术语也叫做HOOK钩子

Target

  1. package org.example;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Target;
  4. public class Main {
  5. //测试调用我们的MyAnnotation方法
  6. @MyAnnotation
  7. public void Test01(){
  8. }
  9. //测试元注解
  10. //定义一个注解
  11. //定于ElementType.METHOD 之后,那么就只能在方法上进行使用,其它的方法可以参考官方文档
  12. @Target(value = ElementType.METHOD)
  13. //@interface是定义一个接口的意思
  14. @interface MyAnnotation{
  15. }
  16. }


如果是这样定义的话,那么就只能放在方法上

如果像写在类上的话,在target中可以定义新增一个参数,这样的话就可以在类中调用这个接口了
@Target(value = {ElementType.METHOD,ElementType.TYPE})

@Retention

@Retention 表示我们的注解在什么地方还有效

  1. @Target(value = {ElementType.METHOD,ElementType.TYPE})
  2. @Retention(value = RetentionPolicy.RUNTIME)
  3. @interface MyAnnotation{
  4. }

Documented
表示是否将我们的注解声称在JAVAdoc中
Inherited
意思就是注解的子类可以继承父类的注解


起步

annoutation

这里给他定义一个接口,叫做MyAnnotation

  1. import javax.swing.text.Element;
  2. import java.lang.annotation.*;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. public class Main {
  6. //这里定义了第一个注解MyAnnotation @interface只是一个接口而已
  7. //这个要自定义注解,那么就要加上@Target 和 @ Retention
  8. @Target({ElementType.TYPE,ElementType.METHOD})
  9. @Retention(RetentionPolicy.RUNTIME)
  10. @interface MyAnnotation{}
  11. }
  12. ```然后添加一些元注解
  13. ```java
  14. package org.kuang.annoutation;
  15. import java.lang.annotation.ElementType;
  16. import java.lang.annotation.Target;
  17. public class Test01 {
  18. @MyAnnotation(name = "小红") //调用注解
  19. public class Test02{
  20. }
  21. }
  22. //定义一个注解
  23. //target中的参数的意思是 1、METHOD允许在方法上定义。2、TYPE允许在类上定义
  24. @Target({ElementType.METHOD,ElementType.TYPE})
  25. @interface MyAnnotation{
  26. //注解的参数必须为:参数类型+参数名()
  27. String name () default ""; //定义一个空的参数
  28. }

可以多写一些参数,例如

  1. @Target({ElementType.METHOD,ElementType.TYPE})
  2. @interface MyAnnotation{
  3. String name() default ""; //定义一个空的参数
  4. int age() default 0;
  5. int id() default -1; //如果默认代表为-1,那么则显示不存在
  6. String[] schools() default {"清华","北大"};
  7. }

default代表着默认值的意思,当我们定义为默认值之后,那么就可以不用进行传参,因为已经默认定好了值

  1. import javax.swing.text.Element;
  2. import java.lang.annotation.*;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. public class Main {
  6. //这里将会调用@MyAnnotation注解
  7. @MyAnnotation(age = 1,name = "赵日天")
  8. public void test(){
  9. }
  10. //这里定义了第一个注解MyAnnotation @interface只是一个接口而已
  11. //这个要自定义注解,那么就要加上@Target 和 @ Retention
  12. @Target({ElementType.TYPE,ElementType.METHOD})
  13. @Retention(RetentionPolicy.RUNTIME)
  14. @interface MyAnnotation{
  15. //注解中的参数要这样去定义: 参数类型 + 参数名();
  16. String name() default ""; //如果调用MyAnnotation中的name不赋值的话,默认为空,default就是定义他为空的意思
  17. int age();
  18. int id() default -1;
  19. String[] Schools() default {"西部牛仔","美国华盛顿职业技术学院"}; //这里变量列表定义了两个参数
  20. }
  21. }
  22. ```如果你想定义注解只有一个值的情况,可以这样编写
  23. ```java
  24. @MyAnnotation1("李天龙")
  25. public void test2(){
  26. }
  27. //如果你想定义注解只有一个值的情况,可以这样编写
  28. @Target({ElementType.TYPE,ElementType.METHOD})
  29. @Retention(RetentionPolicy.RUNTIME)
  30. @interface MyAnnotation1{
  31. //如果只有一个参数的情况下,建议用value来命名
  32. String value();
  33. }

反射相关的主要API

  1. java.lang.Class 代表一个类
  2. java.lang.reflect.Method 代表一个类的方法
  3. java.lang.reflect.Field 代表类的成员变量
  4. java.lang.reflect.Constructor 代表类的构造器

首先我们先定义一个实体类,私有的
java类中的get 和set构造是什么意思?有什么用?什么场景下使用?

小解

get和set是Java类中的两种常见方法,用于获取和设置类的属性值。get方法用于获取属性值,set方法用于设置属性值。
这两种方法的作用是为了保护类的属性,防止外部直接访问和修改类的属性值,从而保证类的封装性和安全性。同时,get和set方法也提供了一种方便的方式来访问和修改类的属性值。
在Java编程中,通常情况下,我们会将类的属性设置为私有的(private),这样外部就无法直接访问和修改属性值。而通过get和set方法,我们可以在类的内部控制属性的访问和修改,从而保证了类的封装性和安全性。
使用get和set方法的场景非常广泛,例如在Java Web开发中,我们通常会使用JavaBean来封装表单数据,这时就需要使用get和set方法来获取和设置表单数据的属性值。另外,在Java框架中,也经常使用get和set方法来操作数据库中的数据。

  1. //什么叫反射
  2. public class test1 {
  3. }
  4. //实体类
  5. class User{
  6. private String name;
  7. private int id;
  8. private int age;
  9. //User类中的无参构造
  10. public User() {
  11. }
  12. //User类中的有参构造
  13. public User(String name, int id, int age) {
  14. this.name = name;
  15. this.id = id;
  16. this.age = age;
  17. }
  18. //通常来说类的属性都是私有的,所以我们要设置get和set来进行封装
  19. //我们可以在类的内部控制属性的访问和修改,从而保证了类的封装性和安全性。
  20. public String getName() {
  21. return name;
  22. }
  23. public void setName(String name) {
  24. this.name = name;
  25. }
  26. public int getId() {
  27. return id;
  28. }
  29. public void setId(int id) {
  30. this.id = id;
  31. }
  32. public int getAge() {
  33. return age;
  34. }
  35. public void setAge(int age) {
  36. this.age = age;
  37. }
  38. //再加一个tostring,方便我们写程序时调试
  39. @Override
  40. public String toString() {
  41. return "User{" +
  42. "name='" + name + '\'' +
  43. ", id=" + id +
  44. ", age=" + age +
  45. '}';
  46. }
  47. }

测试

在main方法中进行调试

  1. public class test03 {
  2. public static void main(String[] args) throws ClassNotFoundException {
  3. //通过反射获取class对象
  4. Class c1 = Class.forName("org.kuang.annoutation.User");
  5. System.out.println(c1);
  6. }
  7. }

得到一个Class结果


打印hashcode可以证明 都是一样的,来自同一份文件

  1. package org.kuang.annoutation;
  2. public class test03 {
  3. public static void main(String[] args) throws ClassNotFoundException {
  4. //通过反射获取class对象
  5. Class c1 = Class.forName("org.kuang.annoutation.User");
  6. Class c2 = Class.forName("org.kuang.annoutation.User");
  7. Class c3 = Class.forName("org.kuang.annoutation.User");
  8. Class c4 = Class.forName("org.kuang.annoutation.User");
  9. System.out.println(c1.hashCode());
  10. System.out.println(c2.hashCode());
  11. System.out.println(c3.hashCode());
  12. System.out.println(c4.hashCode());
  13. }
  14. }
  15. //创建实体类
  16. class User{
  17. private String name;
  18. private int id;
  19. private int age;
  20. //创建一个无参构造
  21. public User() {
  22. }
  23. //创建一个有参构造
  24. public User(String name, int id, int age) {
  25. this.name = name;
  26. this.id = id;
  27. this.age = age;
  28. }
  29. //因为我们是private是私有的,所以我们还需要定义get/set
  30. public String getName() {
  31. return name;
  32. }
  33. public void setName(String name) {
  34. this.name = name;
  35. }
  36. public int getId() {
  37. return id;
  38. }
  39. public void setId(int id) {
  40. this.id = id;
  41. }
  42. public int getAge() {
  43. return age;
  44. }
  45. public void setAge(int age) {
  46. this.age = age;
  47. }
  48. //再写一个tostring,方便我们调试
  49. @Override
  50. public String toString() {
  51. return "User{" +
  52. "name='" + name + '\'' +
  53. ", id=" + id +
  54. ", age=" + age +
  55. '}';
  56. }
  57. }

通过反射之后,可以直接调用私有变量中的任何参数

定义一个类,其属性为私有的,定义有参和无参构造,然后定义get和set方法,来封装和保护方法。
到最后也反射调用方法获取方法
也是在main方法中使用Class.forname()函数

用户名金币积分时间理由
Track-魔方 150.00 0 2023-06-07 14:02:07 一个受益终生的帖子~~

打赏我,让我更有动力~

2 条回复   |  直到 2023-6-27 | 653 次浏览

Track-魔方
发表于 2023-6-7

内容相对基础,期待有具体漏洞案例的内容产出

评论列表

  • 加载数据中...

编写评论内容

coteack888
发表于 2023-6-27

我的思念在火星流浪,超级大乐透 我的祝福在珠峰飘荡,我的牵挂在”神六”翱翔,我的依恋在南极冷藏,福彩七乐彩 我的体贴在五湖四海歌唱—无论你离我有多远,都无法逃避我用心绕下的情网。我的思念在火星流浪,我的祝福在珠峰飘荡,我的牵挂在”神六”翱翔,我的依恋在南极冷藏,波场时时彩 我的体贴在五湖四海歌唱—无论你离我有多远,都无法逃避我用心绕下的情网。

评论列表

  • 加载数据中...

编写评论内容
登录后才可发表内容
返回顶部 投诉反馈

© 2016 - 2024 掌控者 All Rights Reserved.