首页 > 其他分享 >注解和反射process6

注解和反射process6

时间:2024-09-02 17:36:14浏览次数:3  
标签:反射 Class System class process6 println 注解 public out

1、注解(Annotation)

一些方法加了一杠表示不推荐使用,但是也能用

写代码时标了黄块的代码体就是警告

1.1注解

  1. 注解(Annotation)——用 @ 符号标示

    不是程序本身,可以对程序作出解释(这一点与注释(comment)没什么区别)

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

    通过反射机制编程实现对辅助信息数据的访问

1.2内置注解

Screenshot_20240825_142657_tv.danmaku.bili

  1. 内置注解(3个)

    package annotation;
    
    import java.util.ArrayList;
    import java.util.List;
    
    //内置注解
    public class TestD1 extends Object{
    
        //@Override  重写的注解
        @Override
        public String toString() {
            return super.toString();
        }
    
        //Deprecated  不推荐程序员使用,但是可以使用,或者存在更好的方式
        @Deprecated
        public static void  test(){
            System.out.println("Deprecated");
        }
    
        //SuppressWarnings 镇压警告,既可以放在方法上,也可以放在类和构造器上面
        @SuppressWarnings(value = "All") //注解只有一个值时,可以把value去掉
        public void test02(){
            List list = new ArrayList<>();
        }
    
        public static void main(String[] args) {
            test();
        }
    }
    

1.3元注解

Screenshot_20240825_144114_tv.danmaku.bili

元注解(注解其他注解,4个meta-annotation)

package annotation;

import java.lang.annotation.*;

//测试元注解
@MyAnnotation
public class TestD2 {
    public void test(){
        
    }
}

//定义一个注解(随便打开一个注解照着写)
//Target 表示我们的注解可以用在那些方面(进去后发现需要定义参数)
@Target(value = {ElementType.METHOD,ElementType.TYPE}) //用在ElementType.METHOD方法和ElementType.TYPE类上

//Retention 表示我们的注解在那些地方还有效
//runtime > class > sources(一般自定义都写在runtime)
@Retention(value = RetentionPolicy.RUNTIME)

//Documented 表示是否将我们的注解生成在JAVAdoc中
@Documented

//Inherited 子类可以继承父类的注解
@Inherited

@interface MyAnnotation{
}

1.4自定义注解(@interface)

Screenshot_20240825_150349_tv.danmaku.bili

package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//自定义注解
public class TestD3 {
    //注解可以显示赋值,如果没有赋值,我们就必须给注解赋值
    @MyAnnotation2(age = 18,name = "yiyi")
    public void test(){
    }

    @MyAnnotation3("erer") //默认value命名,value就可以不写
    public void test2(){}
}

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)

@interface MyAnnotation2{
    //注解的参数:参数类型 + 参数名()+默认;  注解可以显示赋值,如果没有赋值,我们就必须给注解赋值(默认)
    String name() default "";
    int age(); //没有给默认可以直接 @MyAnnotation2(age = 18,name = "yiyi")
    int id() default  -1;//如果默认为-1表示不存在
    String[] schools() default {"奥运比赛","洛杉矶"}; //String[]数组
}

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)

@interface MyAnnotation3{
    String value();//如果只有一个参数,建议使用value命名
}

2、反射(Reflection)

2.1反射

Screenshot_20240825_153225_tv.danmaku.bili

Screenshot_20240825_160733_tv.danmaku.bili

  1. 动态语言

    运行时可以改变结构的语言 JavaScript

  2. 静态语言

    运行时不可以改变结构的语言 java

    java是准动态语言,可以通过反射机制获取类似动态语言特性

  3. 反射

    优点:可以实现动态创建对象和编译,体现很大的灵活性

    缺点:对性能有影响(减慢)

2.2获得反射对象

1.一个类在内存中只有一个class对象
2.一个类被加载后,类的整个结构都会被封装在Class结构中

Screenshot_20240825_162426_tv.danmaku.bili

Screenshot_20240825_162516_tv.danmaku.bili

package reflection;

//什么是反射
public class TestF1 {
    public static void main(String[] args) throws ClassNotFoundException {
        //通过反射获得类的Class对象
        Class c1 = Class.forName("reflection.TestF1");
        System.out.println(c1);

        Class c2 = Class.forName("reflection.TestF1");
        Class c3 = Class.forName("reflection.TestF1");
        Class c4 = Class.forName("reflection.TestF1");

        //如果hashcode相同,就说明是同一个class
        /*
        1.一个类在内存中只有一个class对象
        2.一个类被加载后,类的整个结构都会被封装在Class结构中
         */
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
        System.out.println(c4.hashCode());
    }
}

//实体类 :pojo entity(属性会与数据库映射)
class User{
    private String name;
    private int id;
    private int age;

    public User() {
    }

    public User(String name, int id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        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;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", age=" + age +
                '}';
    }
}

2.2.1得到Class类的几种方式

Screenshot_20240825_162634_tv.danmaku.bili

package reflection;

//测试class类的创建方式有那些
public class TestF2 {
    public static void main(String[] args) throws ClassNotFoundException {
       Person person =  new Student();
        System.out.println("这个人是:"+person.name);

        //方式一:通过对象获得
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());

        //方式二:forname获得
        Class c2 = Class.forName("reflection.TestF2");
        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; //若果是private修饰,需要加set/get,public修饰不用

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

class Student extends Person{
    public Student(){
        this.name = "学生";
    }
}

class Teacher extends Person{
    public Teacher(){
        this.name = "老师";
    }
}

2.2.2所有类型的class对象

package reflection;

import javax.xml.bind.Element;

//按住Alt键可以复制多行
//所有类型的Class对象
public class TestF3 {
    public static void main(String[] args) {

        Class c1 = Object.class; // 类
        Class c2 = Comparable.class; //接口
        Class c3 = String[].class; //一维数组
        Class c4 = Override.class; //注解
        Class c5 = int[][].class;  //二维数组
        Class c6 = Element.class; //枚举
        Class c7 = Integer.class; //基本数据类型
        Class c8 = void.class; //void
        Class c9 = Class.class; //class

        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c4);
        System.out.println(c5);
        System.out.println(c6);
        System.out.println(c7);
        System.out.println(c8);
        System.out.println(c9);

        //只要元素类型和维度一样,就是同一个Class
        int[] a = new int[10];
        int[] b = new int[100];
        System.out.println(a.getClass().hashCode());
        System.out.println(b.getClass().hashCode());
    }
}

2.3类加载内存分析

2.3.1类加载内存分析

Screenshot_20240825_195212_tv.danmaku.bili

Screenshot_20240825_195447_tv.danmaku.bili

package reflection;

import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;

/*类加载内存分析
1.加载到内存产生类对应的class对象
2.链接,链接结束后m=0   注意:所有的常量和静态变量在静态链接阶段就在赋值
3.初始化
     <clinit>(){
                System.out.println("A类静态代码块的初始化");
                m = 300;
                m = 100;
     }
     m =100
 */
public class TestF4 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(A.m);
    }
}

class A{
    static{
        System.out.println("A类静态代码块的初始化");
        m = 300;
    }

    static int m = 100;

    public A(){
        System.out.println("A类的无参构造器初始化");
    }
}

2.3.2分析类初始化

Screenshot_20240825_195825_tv.danmaku.bili

  • 类的主动引用(一定会发生类的初始化)
  • 类的被动应用(不会发生类的初始化)
package reflection;

import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;

//测试类什么时候会被初始化
public class TestD5 {
    static {
        System.out.println("Main类被加载");
    }

    public static void main(String[] args) throws ClassNotFoundException {
        //1.主动引用 new(new子类会先主动引用父类)
        //Son son = new Son();

        //2.反射也会产生主动引用(反射子类会先主动引用父类)
        //Class.forName("reflection.Son");

        //不会产生类的引用方法
        //1.子类调用父类的静态方法或者变量
        //System.out.println(Son.b);

        //2.通过数组也不会加载类
        //Son[] array = new Son[5];

        //3.final常量池里的常量——所有的常量和静态变量在静态链接阶段就在赋值
        System.out.println(Son.M);


    }
}

class Father{
    static int b = 2;

    static {
        System.out.println("父类被加载");
    }
}

class Son extends Father{
    static{
        System.out.println("子类被加载");
        m = 300;
    }

    static int m = 100;
    static final int M = 1;
}

2.4类加载器的作用

  • 引导类加载器:负载java平台核心库

  • 扩展类加载器:jre/lib/ext目录下的jar包装入工作库

  • 系统类加载器:classpath/path目录下的类或者jar包装入工作,是最常用的加载器

    Screenshot_20240825_201919_tv.danmaku.bili

package reflection;

public class TestF5 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取   系统类的加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

        //获取系统类加载器的父类加载器-->扩展类加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);

        //获取扩展类加载器的父类加载器-->根类加载器(C/C++)
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);

        //测试当前类是那个加载器加载的(系统类加载器)
        ClassLoader classLoader = Class.forName("reflection.TestF5").getClassLoader();
        System.out.println(classLoader);

        //测试JDK内部的类是谁加载的(根加载器)
        classLoader = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader);

        //如何获得系统类加载器可以加载的路径
        System.out.println(System.getProperty("java.class.path"));
        /*
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\charsets.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\deploy.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\ext\access-bridge-32.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\ext\cldrdata.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\ext\dnsns.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\ext\jaccess.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\ext\jfxrt.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\ext\localedata.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\ext\nashorn.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\ext\sunec.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\ext\sunjce_provider.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\ext\sunmscapi.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\ext\sunpkcs11.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\ext\zipfs.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\javaws.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\jce.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\jfr.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\jfxswt.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\jsse.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\management-agent.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\plugin.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\resources.jar;
        C:\Program Files (x86)\Java\jdk1.8.0_191\jre\lib\rt.jar;
        D:\Java-Code\Process\Process6\process6\out\production\kuang2;
        D:\Idea\IntelliJ IDEA 2024.1.4\lib\idea_rt.jar
         */

        //双亲类委派机制——一级一级网上找(保证安全性)
    }
}

3、获取

Screenshot_20240825_204317_tv.danmaku.bili

3.1获取类的信息

package get;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

//获取类的信息
public class TestG1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("reflection.User");
        //获得类的名字
        System.out.println(c1.getName());//获得包名+类名
        System.out.println(c1.getSimpleName());//获得类名

        //获得类的属性
        System.out.println("=======================================");
        Field[] fields = c1.getFields();//有没有s是一个属性和一堆属性的区别
        //只能找到public属性

        fields = c1.getDeclaredFields();
        //可以找到全部的属性
        for(Field field : fields){ //field.for生成,打印这些属性
            System.out.println(field);
        }

        Field names = c1.getDeclaredField("name");
        //获得指定的属性
        System.out.println(names);

        //获得类的方法
        System.out.println("==========================");
        Method[] methods = c1.getMethods();
        //获取本类及其父类的全部public方法
        for (Method method : methods) {
            System.out.println("正常的:"+method);
        }
       methods = c1.getDeclaredMethods();
        //获得本类的所有方法,没有父类
        for (Method method : methods) {
            System.out.println("getDeclaredMethods:"+method);
        }

        //获得指定方法
        System.out.println("============================================");
        Method getname = c1.getMethod("getName",null);
        Method setname = c1.getMethod("setName",String.class);//setname及其所需参数类型
        System.out.println(getname);
        System.out.println(setname);

        //获得指定的构造器
        System.out.println("===============================");
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("##"+constructor);
        }

        constructors = c1.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        //获得指定的构造器
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class,int.class);
        System.out.println("指定"+declaredConstructor);
    }
}

3.2通过反射创建对象(User不是公共的报错——没有解决)

package get;

import reflection.User;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

//动态的创建对象,通过反射
//一直报错,不理解为什么一直说User不是公共的,不能用,但老师的能用
public class getG2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //获得Class对象
        Class c1 = Class.forName("reflection.User");

        //构造一个对象
        //User user = (User)c1.newInstance();//本质是调用了类得无参构造器
        //System.out.println(user);

/*  这里不理解为什么一直报错
        //通过构造器创建对象
        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        User user2 = (User)constructor.newInstance("小胖", 001, 18);
        System.out.println(user2);
 */

    }
}

4、分析性能问题(相同问题)

5、出现阻碍——学习止步

标签:反射,Class,System,class,process6,println,注解,public,out
From: https://www.cnblogs.com/moulixu/p/18393157

相关文章

  • Java 反射获得构造方法
        ConstructorExercisepackageConstructorExercise20240831;importClassReflect20240831.Student;importjava.lang.reflect.Constructor;importjava.lang.reflect.InvocationTargetException;publicclassCreateInstance{publicstaticvoidmain......
  • 【类型转换】使用c#实现简易的类型转换(Emit,Expression,反射)
    引言哈喽。大家好,好久不见,最近遇到了一个场景,就是在FrameWork的asp.netmvc中,有个系统里面使用的是EntityFramework的框架,在这个框架里,提供了一个SqlQuery的方法,这个方法很好用啊,以至于在EFCORE8里面又添加了回来,不过不知道性能怎么样,我遇到的场景是通过SqlQuery查询的......
  • Java反射机制:动态访问和修改类属性
    Java反射机制:动态访问和修改类属性大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!Java的反射机制是一种强大的工具,它允许程序在运行时访问和修改类的属性和方法。通过反射,我们可以在不直接引用类的情况下,动态地创建对象、调用方法、修改字段等。本文......
  • Java注解:提升代码可读性与维护性的利器
    Java注解:提升代码可读性与维护性的利器大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在Java编程语言中,注解(Annotations)是一种特殊的接口,用于为类、方法或变量提供元数据。注解可以被用来提供编译时和运行时的额外信息,从而增强代码的可读性和维护性。......
  • Java中的注解详讲
    1什么是注解jdk5提供了一个新的应用Annotation,注解,注释与之前所学的注释的区别之前的注释:是给程序员看,让程序员知道程序(代码)有什么用,实现了什么功能今天的注解:是给编辑器或jvm看的。在编译和运行时提供一些信息,按照信息完成后续的工作我们在开发中经常使用注解作......
  • Java反射
    1.反射1.1.反射引入编译时知道类或对象的具体信息,此时直接对类和对象进行操作即可,无需反射如果编译不知道类或对象的具体信息,就使用反射来实现。比如类名、属性和属性值放在XML文件中,需要在运行时读取XML文件,动态获取类的信息publicclassTest{publicstaticvo......
  • 渗透测试基础-反射型XSS原理及实操
    只为对所学知识做一个简单的梳理,如果有表达存在问题的地方,麻烦帮忙指认出来。我们一起为了遇见更好的自己而努力......
  • 反射(快速入门)
    目录1、什么是反射?2、反射的作用3、Class对象的获取4、Constructor对象的获取5、Method对象获取6、Fieldfi对象的获取Java把类中的属性抽象成了一个Field对象1、什么是反射?反射就是动态加载对象,并对对象进行剖析。在运行状态中,对于任意一个类,都能够知道这个类......
  • springboot 接口接收参数的注解介绍(@RequestParam,@PathVariable,@RequestBody 等)
    springboot接收参数的注解介绍(使用方法)在SpringBoot中,接收参数的方式主要依赖于SpringMVC提供的注解。这些注解帮助你将HTTP请求中的参数绑定到控制器(Controller)方法的参数上。以下是一些常用的接收参数的注解:1.@RequestParam用法:用于将HTTP请求参数绑定到控制器的方......
  • 工作 6 年,@Transactional 注解用的一塌糊涂
    接手新项目一言难尽,别的不说单单就一个@Transactional注解用的一塌糊涂,五花八门的用法,很大部分还失效无法回滚。有意识的在涉及事务相关方法上加@Transactional注解,是个好习惯。不过,很多同学只是下意识地添加这个注解,一旦功能正常运行,很少有人会深入验证异常情况下事务是否能......