JAVA高级-反射与动态代理(十五)

观看尚硅谷视频做的视频笔记

一、高级-反射与动态代理(十四)

1、反射概述

1)java程序中,所有的对象都有两种类型:编译时类型,运行时类型,而很多时候对象的编译类型和运行时类型不一致。

此处就是多态性体现。

Object obj=new String(“hello”);

2)例如:某些变量或形参的声明类型是Object类型,但是程序却需要调用该对象运行时类new String(“hello”);的方法compareTo方法,该方法不是Object中的方法,那么如何解决?

方案1:多态中有用到,向下转型。在编译和运行是都完全知道类型的具体的信息,在这种情况下,我们可以直接先使用instanceof运算符进行判断是否为String类型,若是就利用强制类型转换符将其转成运行时类的变量即可,强制转换后就可以用String里面的方法。缺点:①若用这种方法会写很多instanceof这种判断。②此判断是否全,是否满足需求。此时写好了代码,形参是Object类型。判断obj是否为A类型,是就进行强转,调方法,B类型,C类型,目前只是ABC三个对象。后续可能DEF,也有可能作为参数传进来,就需要进行修改,有没有更好的方案解决此问题,自然而然就考虑方案2.

在这里插入图片描述

方案2:编译时根本无法预知该对象和类的真实信息,程序只能依靠运行时obj已经在内存中,信息来发现该对象和类的真实信息,这就必须使用反射。(程序运行过程中,动态获取所属类的类型obj.getClass,obj对象是哪个类造的,动态获取,及时把类转换成声明,动态的转换,再去调特有的方法就需要用到反射)

obj.getClass在Object中声明
框架中用的比较多。

3)反射是被是视为动态语言的关键,反射机制允许程序在运行期间借助于RelectionAPI取得任何类得内部信息,并能直接操作任意对象得内部属性及方法。(跟对象里面方法属性的权限都无关)

加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象。(一个类只有一个Class对象),这个对象就包含了完整的类的结构的信息。我们可以i通过这个对象看到类的结构,这个对象就像一面镜子,通过这个镜子看到类的结构,所以我们形象的称为反射。

4)代码示例(利用面向对象做的操作 、 使用反射完成调属性方法操作、使用反射完成调私有属性方法操作)

package com.zhou.java;import org.junit.Test;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;public class ReflectionTest {/* 利用反射之前做的操作 */@Testpublic void test1() {//1.创建Person类的实例//   public person()Person p1 = new Person();//2.调用属性、方法p1.age = 10;System.out.println(p1.age);//3.调用方法//public void show(){}p1.show();}//使用反射完成上诉操作@Testpublic void test2() throws Exception {
////1.创建类的实例//person.class就作为Class的实例出现Class<Person> clazz = Person.class;Person p1 = clazz.newInstance();//jdk9之后不建议用System.out.println(p1);//2.调属性、先获取当前类当中叫age名的属性。Field agefield = clazz.getField("age");agefield.set(p1, 10);System.out.println(agefield.get(p1));//3.调方法,先获取当前类当中叫show的方法。Method showmethod = clazz.getMethod("show");showmethod.invoke(p1);}//反射做其他事儿@Testpublic void test3() throws Exception {//1.调用私有的构造器,创建Person实例//   private(String name,int age){}Class clazz1 = Person.class;Constructor cons = clazz1.getDeclaredConstructor(String.class, int.class);//不用填写构造器名称,只需要告诉参数就行,需要传的是String参数和int参数,构造器有了,就需要造对象  cons.setAccessible(true);Person p1 = (Person) cons.newInstance("Tom", 20);System.out.println(p1);//2.调用私有的属性Field namefield = clazz1.getDeclaredField("name");namefield.setAccessible(true);namefield.set(p1, "Jerry");System.out.println(p1);//2.调用私有的方法//private String showNation(){}Method showNation = clazz1.getDeclaredMethod("showNation", String.class);showNation.setAccessible(true);String info = (String) showNation.invoke(p1, "CHN");System.out.println(info);}
}

5)通过使用反射前后的的例子的对比

①面向对象中创建对象,请用指定结构(属性、方法)等功能,可以不使用反射,也可以使用反射,请问有什么区别?

运行时类,运行的代码中,person类就会加载到内存中,放到内存中的类就称为运行时类。

不使用反射:我们需要考虑封装性,比如,出了Person类之后,就不能再调用Person类中的私有结构。使用反射:我们可以调用运行时类中任意的构造器、属性、方法。包括了私有的属性、方法、构造器。

②以前创建对象并调用方法的方式,与现在通过反射创建对象并调用方法的方式对比的话,哪种用的多?

从我们程序员来讲,我们开发中主要是完成义务代码。对于相关的对象,方法的调用都是确定,所以我们使用非反射的方式多一些。

因为反射体现了多态性(可以再运行时动态的获取对象所属的类,动态的调用相关的方法),所以我们在设计框架的时候,会大量的使用反射。

框架=注解+反射(获取相关注解)+设计模式

③单例模式的饿汉式和懒汉式,私有化的构造器,此时通过反射,可以创建单列模式的多个对象吗?

是的,单列模式的饿汉式和懒汉式,构造器都被私有。在类的内部造对象,外部直接用就可以。通过反射可以调构造器。

④.通过反射,可以调用类中私有结构,是否与面对对象的封装有冲突》是不是java语言设计存在bug?

不存在bug

封装性:体现的是否会建议我们调用内部api的问题,比如,private声明的结构,意味着不建议调用。

反射:体现的是我们能否调用的问题,因为类的完整结构都加载到了内存中,我们就有能力进行调用。

反射理解:是假设内存中有一个内存对象,通过这个对象,可以看成是哪个类创建的,通过类可以看到是在哪个包中声明的。

6)java反射机制提供的功能

在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时获取泛型信息
在运行时

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.Class类的理解

在这里插入图片描述
在这里插入图片描述

1)如下以Java类的加载为例说明

编译:针对于编写好的.java源文件进行编译(使用Javac.exe),会生成一个或多个.class字节码文件。
接着,我们使用Java.exe命令对指定的.class字节码文件进行解释运行。这个解释运行的过程中,我们需要将.class字节码文件加载到(使用类的构造器)内存中(方法区),加载到内存的class文件对应的结构即为Class的一个实例

比如:加载到内存中的Person类或String类或User类,都作为Class的一个一个的实例
接口加载到内存中也是对应得一个Class实例

Class clazz1=Person.class;
Class clazz2=String.class;
Class clazz3=User.class;
Class clazz4=Compareable.class;

3.获取Class实例的几种方式(掌握前三种)

import com.zhou.java.Person;
import org.junit.Test;public class ClassTest {//1.调用运行时类的静态属性@Testpublic void test1() throws Exception {Class clazz1 = Person.class;System.out.println(clazz1);//2.调用运行时类的对象的getClass()Person p1 = new Person();Class clazz2 = p1.getClass();System.out.println(clazz1 = clazz2);//true//3.调用Class的静态方法forName(String className)String className = "com.zhou.java.Person";//全类名Class clazz = Class.forName(className);//4.Class systemClassLoader = ClassLoader.getSystemClassLoader().loadClass("com.zhou.java.Person");}}

4.class看作是反射源头

5.Class的实列都可以指向哪些结构呢?

class:外部类,成员(成员内部类,静态内部类)、局部内部类、匿名内部类
interface:接口
[]:数组
enum:枚举
annotation:注解
基本数据类型
void

在这里插入图片描述

6.类的加载过程(详细在jvm中有)

在这里插入图片描述

6.1过程1:loading(装载)

将类的class文件读入内存,并为之创建一个java.lang.Class对象。此过程由加载器完成

6.2过程2linking(连接)

验证、准备、解析
验证(Verify):确保加载的类信息符合JVM规范,例如:以cafebabe开头,没有安全方面的问题。
准备prepare):正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。

解析(Resolve):虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。
在这里插入图片描述

6.3过程3Initialization(初始化)

在这里插入图片描述

6.4关于类的加载器(了解,JDK8版本为例)

1)作用:负责类的加载,并对应一个Class的实例

虽叫类的加载器,不仅能加载类,还能加载接口、没接、注解等
负责将字节码文件放到内存中
在这里插入图片描述

2) 分类(分为两种)

在这里插入图片描述
似乎是继承关系,其实不是继承关系,而是层级关系
在这里插入图片描述
在这里插入图片描述

①BootStrapClassLoader:引导加载器、启动加载器

使用C、c++语言编写的,不能通过java代码获取实例
负载加载java的核心库。(Java_Home/jar/lib/rt.jar)
java代码获取实例,获取的时候返回为null

②继承于ClassLoader的类加载器

扩展类加载器(jdk提供的)
系统类加载器、应用程序类加载器(jdk提供的)自定义的类默认使用的类的加载器
用户自定义类的加载器(Tomcat中也定义了一些类加载器)

在这里插入图片描述
在这里插入图片描述

③代码演示
获取系统类加载器

在这里插入图片描述

获取扩展加载器(获取上一层加载器)

在这里插入图片描述

在这里插入图片描述

获取引导类加载器失败,获取不到。返回值为null

在这里插入图片描述

用户自定义的类是系统类加载加载的
方式一

在这里插入图片描述

方式二

在这里插入图片描述
在这里插入图片描述

3)以上的类的加载器是否存在继承关系

4)掌握使用类的加载器获取流,并读取配置文件信息。

方案一:

propertites处理属性文件
读取配置文件时:
使用单元测试方法,默认就是使用的是当前module下面
在这里插入图片描述
通过propertites读取流当中文件的数据
在这里插入图片描述

处理的key和值都是String类型
在这里插入图片描述
在这里插入图片描述

以后会实现数据和代码的分离
数据会放在具体的配置文件中

使用Classloader也可以做这样的事儿
拿到系统加载器
在这里插入图片描述
作为流拿到一个资源
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

方案二:

7.反射的应用

7.1反射的应用1:创建运行时类的对象

1)如何实现:通过Class的实例调用newInstance()方法即可
2)要想创建对象成功,需要满足
①条件1:要求运行是类必须满足一个空参的构造器。
②条件2:要求提供的空参构造器的权限要足够。

Person类实现了两个接口

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

![在这里插入图片描述](https://img-blog.csdnimg.cn/235dae5963cd448a9876eaaff8a30cd7

在这里插入图片描述
.png)

创建Person对象此处的创建运行时类对象指的是Person类
在这里插入图片描述
当把Person类加载到内存中时
使用Java.exe指令时,走类的加载过程:loading,linking、initilion环节,在方法区就会有一个大的实例。就称为运行时类。

首先有一个大的Class实例,获取实例。
在这里插入图片描述

在这里插入图片描述

per调的是toString方法
在这里插入图片描述

若Person类里没有空参构造器,则抛异常在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

还有一种异常是有构造器但不能用私有权限
在这里插入图片描述

在这里插入图片描述
默认权限,同包别的类能用
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3)回忆:javabean中要求当前类:一个空参构造器,有什么用?
①场景1:子类对象在实例化时,子类的构造器的首行默认调用父类的空参的构造器默认有super()
②场景2:在反射中,经常用来创建运行时类的对象,那么我们要求各个运行时类都提供一个空参构造器,便于我们创建运行时类对象的代码。

在这里插入图片描述

Javabean的要求,当前类是公共的,提供当前类的空参构造器,有属性提供get、set方法、有toString方法、重写equals、hashcode方法,是为了防止将对象放在集合中、toString方法(打印对象变量时,打印地址、打印属性的值)

为啥要有这个提供空参构造器这个要求?

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

package com.zhou.java;public class Creature<T> {boolean gender;public int id;public void breath(){System.out.println("呼吸");}private void info(){System.out.println("我是一个生物");}
}
package com.zhou.java;public interface myInterface {void method();}
package com.zhou.java;import org.junit.Test;public class NewInstanceTest {@Testpublic void test() throws InstantiationException, IllegalAccessException {Class clazz = Person.class;//获取Person类的实例Person per = (Person) clazz.newInstance();System.out.println(per);//调的是toString()方法}}
package com.zhou.java;public class Person extends Creature<String> implements Comparable, myInterface {private String name;public int age = 1;private static String info;private Person(String name, int age) {this.name = name;this.age = age;}protected Person(int age) {this.age = age;}protected Person(String name) {this.name = name;}Person() {System.out.println("person()========");}public void show() {System.out.println("您好我是一个Person");}private String showNation(String nation, int age) {System.out.println("shownation");return "我的国籍是:" + nation + ",生活了" + age + "年";}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}public static void showInfo() {System.out.println("我是一个人");}@Overridepublic void method() {}@Overridepublic int compareTo(Object o) {return 0;}
}
4)在jdk标识为过时,替换成什么结构

通过Constructor类调用newInstance()

7.2反射的应用2:获取运行时类所有的结构

1)获取运行时类的内部结构1:所有属性、所有方法、所有构造器
2)获取运行时类的内部结构1:父类、接口们、包、贷泛型的父亲、父亲的泛型

在这里插入图片描述
在这里插入图片描述

package com.atguigu03.reflectapply.apply2;import com.atguigu03.reflectapply.data.Person;
import org.junit.Test;import java.lang.reflect.Field;
import java.lang.reflect.Modifier;/*** @author shkstart* @create 14:28*/
public class FieldsTest {@Testpublic void test1() {Class clazz = Person.class;//getFields():获取到运行时类本身及其所有的父类中声明为public权限的属性Field[] fields = clazz.getFields();for (Field f : fields) {System.out.println(f);}//getDeclaredFields():获取当前运行时类中声明的所有属性Field[] declaredFields = clazz.getDeclaredFields();for (Field f : declaredFields) {System.out.println(f);}}//权限修饰符  变量类型  变量名@Testpublic void test2() {Class clazz = Person.class;Field[] declaredFields = clazz.getDeclaredFields();for (Field f : declaredFields) {//1.权限修饰符/** 0x是十六进制* PUBLIC           = 0x00000001;  1    1* PRIVATE          = 0x00000002;  2	10* PROTECTED        = 0x00000004;  4	100* STATIC           = 0x00000008;  8	1000* FINAL            = 0x00000010;  16	10000* ...** 设计的理念,就是用二进制的某一位是1,来代表一种修饰符,整个二进制中只有一位是1,其余都是0** mod = 17          0x00000011* if ((mod & PUBLIC) != 0)  说明修饰符中有public* if ((mod & FINAL) != 0)   说明修饰符中有final*/int modifier = f.getModifiers();System.out.print(modifier + ":" + Modifier.toString(modifier) + "\t");//            //2.数据类型Class type = f.getType();System.out.print(type.getName() + "\t");
//
//            //3.变量名String fName = f.getName();System.out.print(fName);
//System.out.println();}}
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
得到的都是Person类声明的,父类的没有

在这里插入图片描述
在这里插入图片描述
获取每一个具体的信息
在这里插入图片描述
f.getModifiers()获取修饰符
在这里插入图片描述
类调里面的toString方法,可以看到权限修饰符
在这里插入图片描述
怎么做的?因为modifer这个数在Modifer这个类中有对应的十六进制对应关系
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

获取方法
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

都是当前类中有的
在这里插入图片描述

package apply2;import com.zhou.java.Person;
import org.junit.Test;import java.lang.reflect.Method;public class MethodTest {@Testpublic void test1() {Class clazz = Person.class;/*  //getMethods():获取到运行时类本身及其所有的父类中声明为public权限的方法Method[] methods = clazz.getMethods();for (Method m:methods) {System.out.println(m);}*///getDeclareMethods():获取当前运行时类中声明的所有方法Method[] declaredMethods = clazz.getDeclaredMethods();for (Method m : declaredMethods) {System.out.println(m);}}}
package apply2;import com.zhou.java.Person;
import org.junit.Test;import java.lang.reflect.Field;
import java.lang.reflect.Modifier;public class FieldsTest {//权限修饰符、变量类型、变量名@Testpublic void test2() {Class clazz = Person.class;Field[] fields = clazz.getDeclaredFields();for (Field f : fields) {//1.权限修饰符int modifier = f.getModifiers();System.out.print(modifier + ":" + Modifier.toString(modifier) + "\t");//2.数据类型Class type = f.getType();System.out.println(type.getName() + "\t");//3.变量名String sname = f.getName();System.out.println(sname);System.out.println();}}@Testpublic void test1() {Class clazz = Person.class;//getFields():获取到运行时类本身及其所有的父类中声明为public权限的属性/*Field[] fields = clazz.getFields();for (Field c:fields) {System.out.println(c);}*///getDeclareFields():获取当前运行时类中声明的所有属性Field[] declaredFields = clazz.getDeclaredFields();for (Field f : declaredFields) {System.out.println(f);}}
}

在这里插入图片描述
person里使用了注解
在这里插入图片描述
自定义注解,要想在反射中获取注解及注解的信息,需要求注解的生命周期长

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
首先有大的实例,指明全类名
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
person继承时带泛型
在这里插入图片描述
希望结果里带上泛型
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一个类可以实现多个接口,所以就是数组
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

什么时候用到,泛型写apply时
自定义泛型时,写dao时,dao通用的增删改查操作
操作的哪个表暂时不确定,回到Java层面哪个类不确定?

有可能需要当前类中继承的方法,有一些需要重写,有一些需要继承父类调用的方法,在这里需要获取这里这个类继承的父类的泛型
在这里插入图片描述
获取某一个对象,就不用传大的Class

获取Person类的实例,希望打印出String
先获取带泛型的父类
在这里插入图片描述

在这里插入图片描述
也有可能这个类,父类没有泛型,
也有可能有泛型,若有泛型就进行强转。

在这里插入图片描述
数组就是泛型参数构成的
在这里插入图片描述
角标0就是想要的String
在这里插入图片描述

在这里插入图片描述
不想要class,就获取class名字
调getname()调不了
是因为目前看到的是Type
在这里插入图片描述

Type是Class实现的接口
强转成Class
在这里插入图片描述
然后再进行Class.getName
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

package apply2;import org.junit.Test;import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;public class OtherTest {//获取运行时类的内部结构2:父类、接口们、包、带泛型的父类、父类的泛型等//5.获取运行时类的父类的泛型(难)@Testpublic void test5() throws ClassNotFoundException {Class clazz = Class.forName("com.zhou.java.Person");//获取带泛型的父类(Type是一个接口,Class实现了此接口)Type genericSuperclass = clazz.getGenericSuperclass();System.out.println(genericSuperclass);//如果父类是带泛型的,进行强转为ParameterizedTypeParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;//调用getActualTypeArguments()获取泛型的参数,结果是一个数组,因为可能有多个泛型参数。Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();//获取泛型参数的名称System.out.println(((Class) actualTypeArguments[0]).getName());}//4.获取运行时类所在的包@Testpublic void test4() throws ClassNotFoundException {Class clazz = Class.forName("com.zhou.java.Person");Package aPackage = clazz.getPackage();System.out.println(aPackage);}//3.获取运行时类实现的接口@Testpublic void test3() throws ClassNotFoundException {Class clazz = Class.forName("com.zhou.java.Person");Class[] interfaces = clazz.getInterfaces();for (Class i : interfaces) {System.out.println(i);}}//1.获取运行时类的父类@Testpublic void test1() throws ClassNotFoundException {Class clazz = Class.forName("com.zhou.java.Person");Class superclass = clazz.getSuperclass();System.out.println(superclass);}//2.获取运行时类的带泛型的父类@Testpublic void test2() throws ClassNotFoundException {Class clazz = Class.forName("com.zhou.java.Person");Type genericSuperclass = clazz.getGenericSuperclass();System.out.println(genericSuperclass);}}
package apply2;import com.zhou.java.Person;
import org.junit.Test;import java.lang.reflect.Method;public class MethodTest {@Testpublic void test1() {Class clazz = Person.class;/*  //getMethods():获取到运行时类本身及其所有的父类中声明为public权限的方法Method[] methods = clazz.getMethods();for (Method m:methods) {System.out.println(m);}*///getDeclareMethods():获取当前运行时类中声明的所有方法Method[] declaredMethods = clazz.getDeclaredMethods();for (Method m : declaredMethods) {System.out.println(m);}}}
package apply2;import com.zhou.java.Person;
import org.junit.Test;import java.lang.reflect.Field;
import java.lang.reflect.Modifier;public class FieldsTest {//权限修饰符、变量类型、变量名@Testpublic void test2() {Class clazz = Person.class;Field[] fields = clazz.getDeclaredFields();for (Field f : fields) {//1.权限修饰符int modifier = f.getModifiers();System.out.print(modifier + ":" + Modifier.toString(modifier) + "\t");//2.数据类型Class type = f.getType();System.out.println(type.getName() + "\t");//3.变量名String sname = f.getName();System.out.println(sname);System.out.println();}}@Testpublic void test1() {Class clazz = Person.class;//getFields():获取到运行时类本身及其所有的父类中声明为public权限的属性/*Field[] fields = clazz.getFields();for (Field c:fields) {System.out.println(c);}*///getDeclareFields():获取当前运行时类中声明的所有属性Field[] declaredFields = clazz.getDeclaredFields();for (Field f : declaredFields) {System.out.println(f);}}
}

7.3反射的应用3:调用指定的结构、指定的属性、方法、构造器

在这里插入图片描述

在这里插入图片描述
还是针对Person类

在这里插入图片描述
age非静态,获取它的值,跟对象打交道
创建当前类的对象
在这里插入图片描述
创建Person类的实例

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

获取当前类中名字叫age属性,File是java.lang包下的子类
在这里插入图片描述
在这里插入图片描述

这个属性是实例变量,得跟对象打交道
得说明是哪一个对象的值,是per对象的
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

因为此处是默认权限
在这里插入图片描述
改成public
在这里插入图片描述
在这里插入图片描述
设置属性的值
在这里插入图片描述

在这里插入图片描述

package apply3;import com.zhou.java.Person;
import org.junit.Test;import java.lang.reflect.Field;public class ReflectTest {//反射的应用:调用指定的属性// public int age = 1;@Testpublic void test() throws Exception {Class clazz = Person.class;Person person = (Person) clazz.newInstance();//1.获取运行时类指定名的属性Field agefield = clazz.getField("age");System.out.println(agefield.get(person));//2.获取或设置属性的值agefield.set(person, 2);System.out.println(agefield.get(person));}}

操作私有权限的属性
按age代码重先更改为name
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

package apply3;import com.zhou.java.Person;
import org.junit.Test;import java.lang.reflect.Field;public class ReflectTest {//private String name;@Testpublic void test2() throws  Exception{Class clazz = Person.class;Person person = (Person)clazz.newInstance();//1.通过Class实例调用getDeclareField(String fieldName)获取运行时类指定的属性Field namefield = clazz.getDeclaredField("name");//2、确保此属性可以访问namefield.setAccessible(true);//3、通过Filed类的实例调用get(Object obj)获取// 或设置此属性的值set(Object obj,Object value)namefield.set(person,"Tom");System.out.println(namefield.get(person));}}

在这里插入图片描述

调用静态属性
在这里插入图片描述

在这里插入图片描述
infoField.get()里参数不写不行,因为他不是可变参数。写null是没问题的。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
怎么理解此处null?获取属性时就是用Class获取的,clazz就是Person.class
在这里插入图片描述
若是实例变量,就必须要传对象
在这里插入图片描述

在这里插入图片描述

public class ReflectTest {//调用静态属性// private static String info;@Testpublic void test3() throws  Exception{Class clazz = Person.class;Field infofield = clazz.getDeclaredField("info");infofield.setAccessible(true);/* infofield.set(Person.class,"我是一个人");System.out.println(infofield.get(Person.class));
*/infofield.set(null,"我是一个人");System.out.println(infofield.get(null));}}

在这里插入图片描述

这里是引用

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
这里为啥不能写Integer
在这里插入图片描述
因为不同类型的值才可以自动装箱,此处是类型
int class和Integer class 显然是不同的实例
这叫自动装箱
在这里插入图片描述
在这里插入图片描述
正常情况下,非静态方法用对象去调,传实参
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
发现方法有返回值,返回值怎么体现呢?
~~删除在这里插入图片描述

invoke方法的返回值就是shownation的返回值
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

import java.lang.reflect.Field;
import java.lang.reflect.Method;public class ReflectTest {//反射应用3-2:调用指定的方法// private String showNation(String nation, int age){}@Testpublic void test4() throws Exception{Class clazz = Person.class;Person person =(Person) clazz.newInstance();//1.通过Class的实列调用getDeclareMethod(String methodName,Claass...args)获取指定的方法Method showNation = clazz.getDeclaredMethod("showNation", String.class, int.class);//2.setAccessible(true);确保此方法是可以调用的showNation.setAccessible(true);//3.通过Method实例调用invoke(Onject obj,objs)即为对Method对应的方法调用//invoke()返回值即为Method对应的返回值//特别的,如果Method对应的返回值类型为void,则invoke()返回值为bullObject invoke = showNation.invoke(person, "CHN", 10);System.out.println(invoke);}

在这里插入图片描述
涉及静态方法
在这里插入图片描述

在这里插入图片描述

package apply3;import com.zhou.java.Person;
import org.junit.Test;import java.lang.reflect.Field;
import java.lang.reflect.Method;public class ReflectTest {//调用静态方法// public static void showInfo() {}@Testpublic void test5() throws  Exception{Class clazz = Person.class;Method declaredMethod = clazz.getDeclaredMethod("showInfo");declaredMethod.setAccessible(true);Object invoke = declaredMethod.invoke(null);System.out.println(invoke);}}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package apply3;import com.zhou.java.Person;
import org.junit.Test;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;public class ReflectTest {//调用指定构造器@Testpublic void test6() throws Exception{Class clazz= Person.class;Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class);constructor.setAccessible(true);Person per = (Person)constructor.newInstance("Tom", 12);System.out.println(per);}
}

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
框架大量使用注解
框架使用反射去读注解,根据注解属性值做相应处理
熟悉常用注解,知道注解怎么赋值
参照SupperssWarming,他怎么写,我们就怎么写,
在这里插入图片描述

Table修饰类、接口类型
在这里插入图片描述

在这里插入图片描述
注解能让我们获取就的是Runnntime在这里插入图片描述
在类的声明处就可以使用
此处为什么报错
没有进行赋值
在这里插入图片描述
在这里插入图片描述
此处可以进行默认赋值
在这里插入图片描述

此处就不再报错

反射复习
1.反射的概述(熟悉)
Java给我们提供了一套API
在这里插入图片描述
运行时动态获取指定对象所属类(通过对象调getClass)

在这里插入图片描述
API
在这里插入图片描述
在这里插入图片描述

2.Class的源头

3.类的加载过程、类的加载器(理解)

4.反射的应用1:创建运行时类的对象
5.反射的应用2:获取运行时类所有的结构
6.反射的应用3:调用指定的结构:属性、方法、构造器
7.反射的应用4:注解的使用
8.体会反射的动态性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/849933.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

workerman error 2 send buffer full and drop package

来源 报错信息&#xff1a;workerman error 2 send buffer full and drop package 定时发送数据的时候&#xff0c;本地偶尔出现这种情况 线上第一条数据发出去就报错了&#xff0c;数据改小一点可以发&#xff0c;不过一会还是会出现这种情况。 解决 根据我的经验&#xf…

SAP HCM OPT函数作用

导读 INTRODUCTION OPT函数&#xff1a;SAP HCM工资核算是很多函数的汇总集&#xff0c;原有有兴趣问过SAP的人为什么SCHEMA需要这样设计&#xff0c;SAP的人说是用汇编的逻辑设计的&#xff0c;当时是尽可能用机器语言加速速度读取&#xff0c;每个函数都有对应的业务逻辑代码…

React实战(一)初始化项目、配置router、redux、axios

(一)初始化项目 1.安装项目 npx create-react-app 项目名 编译报错&#xff1a; 解决办法&#xff1a;安装最新的babel-preset-react-app npm install babel-preset-react-applatest 2.配置项目 (1)配置文件目录 (2)使用craco配置webpack.config npm install craco/crac…

Coze入门指南:创建Bot时,如何写好人设与回复逻辑(Persona Prompt)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 Coze Bot 📒📝 Persona & Prompt🌟 # Character🌟 ## Skills🌟 # Overall Rules to follow🌟 ## Workflow🌟 ## Constraints📝 通用写法与模板📝 示例🌟技巧和注意事项⚓️ 相关链接 ⚓️📖 介绍 📖…

免费使用GPT-4生成图片的方法

写在前言 hello&#xff0c;大家好&#xff0c;我是一点&#xff0c;喜欢编程&#xff0c;目前持续在关注AI领域的发展&#xff0c;希望可以结交一些有意思的朋友。 大家可以关注我的公号&#xff1a;【一点sir】&#xff0c;了解更多文章&#xff0c;希望可以和你们成为朋友…

VSCode前端环境配置:从入门到精通的全方位指南

VSCode前端环境配置&#xff1a;从入门到精通的全方位指南 在前端开发的世界里&#xff0c;一款强大的代码编辑器是不可或缺的工具。Visual Studio Code&#xff08;简称VSCode&#xff09;以其丰富的功能、强大的扩展性和简洁的界面设计&#xff0c;赢得了广大前端开发者的青…

OpenCompass 大模型评测平台C-Eval 基准任务评估实战

1. 引言 在人工智能迅速发展的今天&#xff0c;大型语言模型&#xff08;LLMs&#xff09;在多个领域展现出了巨大的潜力和应用价值。然而&#xff0c;如何评价这些模型的性能&#xff0c;了解它们的优缺点&#xff0c;成为了一个重要课题。OpenCompass&#xff0c;一个由上海…

鸿蒙emitter 订阅事件封装 EmitterUtils

适用于api11 和api12 废话不多说&#xff0c;直接上代码 import emitter from ohos.events.emitter; import { StringUtils } from ohos/flutter_ohos;export class EmitterUtils{/*** 发射字符串类型的* param eventId* param data*/public static sendEvent(eventId:stri…

使用Cython编译Python源码加密加速,有这一篇就够了!

0 前言 python是一门脚本语言&#xff0c;运行时由python虚拟机解释执行。当我们使用python设计好算法给第三方使用时只能提供源码&#xff0c;任何运行我们算法的人都可以看到源码以及对应的算法思路。因此&#xff0c;需要一定手动保护源码。 最简单的保护方式是使用代码混…

高光谱图像聚类的像素-超像素对比学习与伪标签校正

Pixel-Superpixel Contrastive Learning and Pseudo-Label Correction for Hyperspectral Image Clustering 文章目录 Pixel-Superpixel Contrastive Learning and Pseudo-Label Correction for Hyperspectral Image Clustering摘要引言相关方法对比学习 方法超像素对比学习像素…

深入Vue.js:从基础到进阶的全面学习指南

简介 Vue.js是什么Vue.js的历史和版本演进Vue.js的优势和适用场景 基本概念 MVVM模式Vue实例模板语法数据绑定计算属性和侦听器 核心功能 指令事件处理表单处理组件系统插槽 进阶功能 动态组件异步组件自定义指令混入插件 状态管理 Vuex介绍核心概念&#xff1a;State、Get…

【嵌入式】智能系统优化:【C++】驱动的【机器学习】与【数据挖掘】技术

目录 一、嵌入式系统简介 二、C在嵌入式系统中的优势 三、机器学习在嵌入式系统中的挑战 四、C实现机器学习模型的基本步骤 五、实例分析&#xff1a;使用C在嵌入式系统中实现手写数字识别 1. 数据准备 2. 模型训练与压缩 3. 模型部署 六、优化与分析 1. 模型优化 模…

什么时候用C而不用C++?

做接口只用C&#xff0c;千万别要C。C是编译器敏感的&#xff0c;一旦导出的接口里有 std::string这些东西&#xff0c;以及类&#xff0c;注定了要为各个编译器的各个版本准备独立的库。 刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C的资料从专业入门…

Gitlab---添加描述模版

0 Preface/Foreword Gitlab是代码托管平台&#xff0c;DevOps。因其免费&#xff0c;被广泛使用。GitLab不但可以管理代码&#xff0c;也可以管理issue&#xff0c;创建milestone等等。针对issue管理&#xff0c;支持描述模版功能&#xff0c;即对于新建的issue&#xff0c;可…

深度网络学习笔记(二)——Transformer架构详解(包括多头自注意力机制)

Transformer架构详解 前言Transformer的整体架构多头注意力机制&#xff08;Multi-Head Attention&#xff09;具体步骤1. 步骤12. 步骤23. 步骤34. 步骤4 Self-Attention应用与比较Self-Attention用于图像处理Self-Attention vs. CNNSelf-Attention vs. RNN Transformer架构详…

【第11章】SpringBoot实战篇之文章(下)含条件分页

文章目录 前言一、文章列表查询1. ArticleController2. ArticleService 二 、文章查询1. ArticleController2. ArticleService 三、文章更新1. ArticleController2. ArticleService 四、文章删除1. ArticleController2. ArticleService 五、文章列表查询(条件分页)1.ArticleCon…

速盾:cdn加速 app

CDN&#xff08;Content Delivery Network&#xff09;加速是通过将网站的静态资源&#xff08;如图片、脚本、样式表等&#xff09;分发到全球多个服务器节点上&#xff0c;使用户能够快速访问这些资源。在移动应用开发中&#xff0c;CDN加速也能够为app提供更快的用户体验和更…

医疗器械网络安全风险管理的基本步骤

医疗器械网络安全风险管理是一个复杂的过程&#xff0c;涉及到多个环节和步骤。以下是一些基本的步骤和关键点&#xff1a; 风险识别&#xff1a;首先需要对医疗器械的软件、网络连接和通信协议等进行漏洞分析&#xff0c;识别潜在的安全漏洞和弱点。这可能涉及对设备的渗透测…

[大师C语言(第二十三篇)]C语言常用第三方库总结

C语言因其高效、灵活和可移植的特性&#xff0c;在系统编程、嵌入式开发、操作系统、网络编程等领域被广泛使用。C语言的标准库提供了一些基础功能&#xff0c;但在实际开发中&#xff0c;开发者通常需要借助第三方库来完成更加复杂的任务。本文将总结一些常用的C语言第三方库&…

MbedTLS源码跨平台编译(window/macos/linux)

1.window平台编译: 克隆: git clone --recursive https://github.com/Mbed-TLS/mbedtls.git 克隆成功 添加OpenSSL环境变量 验证环境 使用cmake编译 cmake ../生成配置时出错 出现上面原因是克隆下来的library与programs及tests目录少文件了,直接下载zip包替换library目录