Java基础学习Day15--反射机制


今天又没什么业务
今天学习了java的反射机制,javase基础也算是告一段落了
女朋友今天回家了 有点桑心5555o(╥﹏╥)o


1.概念

java反射机制可通过类的全路径名对类进行动态加载实例化,获取类信息及类里面的成员变量,方法,改造方法等;加载完类之后,在堆中就产生了一个Clas类型的对象(一个类只有一个对象),这个对象包含了类的完整结构信息,通过这个对象可以得到类的结构(方法,构造方法,属性,结构)。

2.反射的原理

在这里插入图片描述

3.反射的用途:

(1)反编译:.class–>.java
(2)通过反射机制访问java对象的属性,方法,构造方法等
(3)当我们在使用IDE,比如Ecplise时,当我们输入一个对象或者类,并想调用他的属性和方法是,一按点号,编译器就会自动列出他的属性或者方法,这里就是用到反射。
(4)反射最重要的用途就是开发各种通用框架。比如很多框架(Spring)都是配置化的(比如通过XML文件配置Bean),为了保证框架的通用性,他们可能需要根据配置文件加载不同的类或者对象,调用不同的方法,这个时候就必须使用到反射了,运行时动态加载需要的加载的对象。

4.反射的优缺点:

优点:在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。

缺点:
(1)反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;
(2)反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。

5.使用

(1)在运行时判断任意一个对象所属的类
(2)在运行时构造任意一个类的对象
(3)在运行时得到任意一个类所具有的成员变量和方法
(4)在运行时调用任意一个对象的成员变量和方法
(5)生成动态代理

6.反射相关类

java.lang.refiect
java.lang.Class:代表一个类
java.lang.refiect.Method:代表类的方法
java.lang.refiect.Field:代表类的成员变量
java.lang.refiect.Constructors:代表类的构造方法

7.Class类分析

(1)class也是类,继承object类
(2)创建类
①传统方式:

/**
* public Class<?> loadClass(String name) throws ClassNotFoundException {
* return loadClass(name, false);
* }
*/
Student student=new Student();

②java反射:

Class aClass = Class.forName(com.example.content.test.Student);

对于某个类的class类对象,在内存中只存在一份,因此类只加载一次
③每个类的实例都知道他是由哪个class实例所生成
④通过class对象可以完整地得到一个类的完整结构,通过一系列api
⑤class对象放在堆空间
⑥类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据(包括方法名,变量等等)

8.Class类的常用方法

 //通过类路径获取类
        Class aClass = Class.forName("com.example.content.test.Student");
        System.out.println(aClass);//显示cla对象,是哪个类的Class对象
        System.out.println(aClass.getClass());//运行类型
        //得到包名
        Package aPackage = aClass.getPackage();
        System.out.println(aPackage);
        //得到全类名
        String className = aClass.getName();
        System.out.println(className);
        //创建对象实例
        Student student = (Student) aClass.getConstructor().newInstance();
        System.out.println(student);
        //得到属性
        Field nameField = aClass.getField("name");
        System.out.println(nameField.get(student));
        //设置属性
        nameField.set(student, "萌萌猫");
        System.out.println(nameField.get(student));
        //得到所有属性
        Field[] fields = aClass.getFields();
        System.out.println(fields);

9.获取类对象的几种方式:

(1)Class aClass = Class.forName(“com.example.content.test.Student”);
前提:已知类的全路径,且该类在类路径下,通过此方法获取
应用场景:多用于配置文件,读取类全路径,加载类
(2)Class aClass1 = Student.class();
前提:已知具体的类,通过类的class获取,该方式最为安全可靠,程序性能最高
应用场景:多用于参数传递,比如通过反射得到对应构造器对象
(3)Class aClass1 = student.getClass();

10.反射的基本使用:

(1)获得Class:主要有三种方法:
①Object–>getClass
②任何数据类型(包括基本的数据类型)都有一个“静态”的class属性
③通过class类的静态方法:forName(String className)(最常用)
(2)判断是否为某个类的示例:
一般的,我们使用instanceof 关键字来判断是否为某个类的实例。同时我们也可以借助反射中Class对象的isInstance()方法来判断时候为某个类的实例,他是一个native方法。
(3)创建实例:通过反射来生成对象主要有两种方法:
①使用Class对象的newInstance()方法来创建Class对象对应类的实例。

Class<?> c = String.class;
Object str = c.newInstance();

②先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建对象,这种方法可以用指定的构造器构造类的实例。

//获取String的Class对象
Class<?> str = String.class;
//通过Class对象获取指定的Constructor构造器对象
Constructor constructor=c.getConstructor(String.class);
//根据构造器创建实例:
Object obj = constructor.newInstance(“hello reflection”);

(4)通过反射获取构造方法并使用:
①批量获取的方法:
public Constructor[] getConstructors():所有"公有的"构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)

②单个获取的方法,并调用:
public Constructor getConstructor(Class… parameterTypes):获取单个的"公有的"构造方法:
public Constructor getDeclaredConstructor(Class… parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;

③调用构造方法:
Constructor–>newInstance(Object… initargs)
newInstance是 Constructor类的方法(管理构造函数的类)

api的解释为:newInstance(Object… initargs) ,使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

它的返回值是T类型,所以newInstance是创建了一个构造方法的声明类的新实例对象,并为之调用。

11.Java中的成员变量分为两种:

一是没有static修饰的,这些成员变量是对象中的成员,称为实例变量。
二是有static修饰的,称为类变量(静态变量)。

类变量和实例变量的区别是:
类变量在内存中只存一份,在程序运行时,系统只为类变量分配一次内存,只进行一次的初始化。在加载类的过程中完成类变量的内存分配。
类变量可以通过类名访问。
实例变量是属于对象中的成员,每创建一个类的对象,就会为实例变量分配一次内存,实例变量在内存中有多个拷贝,分别属于不同对象,他们之间互不影响。

12.类加载:

(1) 加载过程:加载-连接(验证,准备,解析)-初始化
验证:(验证代码是否jvm的规范,文件格式是否正确,元数据验证,字节码验证,符号引用验证)
准备:(为类中定义的变量,默认初始化并分配空间,即静态变量分配内存并设置变量的初始值,通常情况为该数据类型的“零值”。)
解析(解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,此过程伴随着第二阶段验证中符号引用验证,放到jre中,类处于可运行的状态);
初始化(真正执行类中定义的java程序代码)
(2)类加载的两种形式
静态加载:依赖性太强,编译时加载相关的类,如果没有则报错
动态加载:运行时加载需要的类,如果运行时不用该类,则不报错,依赖性不强

13.通过反射创建对象

(1)方式一:调用类中的public修饰的无参构造器
(2)方式二:调用类中的指定构造器

14.注解

元注解:@Target,Retention,@Document,@Inherited
@Target() :描述注解的使用范围
@Retention:就是我们需要告诉编译器我们需要在什么级别保存该注释信息,用于描述注解的生命周期。
@Document:
@Inherited

常用的内置注解:
@Override:修辞方法,表示打算重写超类中的方法声明。
@Deprecated:这个注释可以修辞方法,属性,类,表示不鼓励程序员使用这样的元素,通常是因为他很危险或有更好的选择。
@SuperWarnings:这个注解主要是用来抑制警告信息的,我们在写程序时,可能会报很多黄线的警告,但是不影响运行,我们就可以用这个注解来抑制隐藏它。与前俩个注解不同的是我们必须给注解参数才能正确使用他。


明天会更好

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TonyLiuys

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值