反射
在程序运行期间可以动态获取类中定义的属性和方法以及构造方法的机制的实现
反射类的核心是Class类程序只能够使用的类每一个都有唯一对应的Class对象
有对象之前必须先有类,static来修饰类的属性和方法。在Java中存储了类的内容,这个内容也应该是一个对象,Java中每一个类都有一个内存,每一块内存都是一个对象,这些对象记录了这些类声明哪些属性和方法以及构造方法,Java将这些类抽象为class类。
Class类的对象不能new,获取Class类的类对象的三种方式
1.通过类名来获取类对象
Class c = EasyClassA.class;
2.通过对象来获取对象
c = new EasyClassA().getClass();
3.通过Class方法的forName方法获取
c= Class.forName("com.easy726.EasyClassA");
反射API:Field 、Method、 Constructor
反射的访问权限会破坏类的封装性
通过反射来获取实例创建对象
T t= tClass.newInstance();//通过类中的无参构造方法创建对象
通过反射获取类中定义的属性
Field[] farr =tClass.getDeclaredFields();
获取属性的名字
String fname = fitem.getName();
获取该属性在Map中的键值对 属性对应的值
Object value = values.get(fname);
设置属性访问权限为true
fitem.setAccessible(true);
fitem.set(t,value);
Java中用来记录类的属性的类叫做Field
使用Filed声明fName变量指向的对象就是Easy类中的name属性,
获取某一个Easy类的对象的name属性的值
Field fName = c.getField("name");
反射获取方法 Method
Easy easy = c.newInstance();
//获取public方法getMethod
Method ma= c.getMethod("methodA");
//调用方法 对象。方法名 面向对象
//method.invoke(对象) 反射
ma.invoke(easy);
示例:
Method mb = c.getMethod("methodB",int.class,int.class);
mb.invoke(easy,23,25);
Constructor用来获取无参构造方法示例
Class<Easy> c = Easy.class;//通过类对象构造无参的对象
Constructor<Easy> con = c.getConstructor();
con.newInstance();
con = c.getConstructor(String.class);
con.newInstance("张三");
getField
功能:用于获取一个公共(public)字段。它只会返回类或接口中声明的公共字段,包括从父类继承的公共字段。
参数:字段名称(String)。
返回值:Field 对象,表示该字段的元数据。
getDeclaredField
功能:用于获取类中声明的任何字段(包括私有的 private、保护的 protected 和默认访问权限字段),不包括从父类继承的字段。
参数:字段名称(String)。
返回值:Field 对象,表示该字段的元数据。
二者关键区别
1.访问权限:
getField:只能访问公共字段。如果字段不是公共的,调用会抛出 NoSuchFieldException。
getDeclaredField:可以访问任何访问权限的字段(private、protected、默认访问权限和 public)。
2.继承的字段:
getField:可以获取类中声明的公共字段,包括从父类继承的公共字段。
getDeclaredField:只能获取当前类中声明的字段,不包括从父类继承的字段。
invoke
invoke 是 java.lang.reflect.Method 类中的一个方法,用于调用通过反射获取的 Method 对象表示的方法。它允许在运行时动态调用对象的方法,而不是在编译时确定。
Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
参数:
obj:要调用方法的对象实例。如果方法是静态的,此参数可以是 null。
args:调用方法时传递的参数,可以是任意数量的参数。
返回值:调用方法的结果。如果方法的返回类型是 void,则返回 null。
异常:
IllegalAccessException:如果当前方法对象不能访问指定的对象或方法。
IllegalArgumentException:如果传递给方法的参数与方法要求的参数类型不匹配。
InvocationTargetException:如果被调用的方法抛出异常。
“内省”是指通过反射机制来分析对象的属性和行为。内省不会破坏封装性
。BeanInfo 是 Java Bean 规范的一部分,它提供了对 Java Beans 进行内省的机制,使开发者能够访问 Bean 的属性、方法和事件。
//获取BeanInfo
BeanInfo bi = Introspector.getBeanInfo(c);
BeanInfo 是指这个接口的实现类实例。这个方法通过反射机制获取关于指定 Java Bean 类的描述信息。
BeanInfo 接口定义了几个方法,用于获取 Bean 的元数据:
getBeanDescriptor():
返回 BeanDescriptor 对象,提供有关 Bean 类的信息,如类名和设计器信息。
getPropertyDescriptors():
返回 PropertyDescriptor 数组,描述 Bean 的属性,包括属性名称、读/写方法等。
getMethodDescriptors():
返回 MethodDescriptor 数组,描述 Bean 的方法,包括方法名称和参数信息。
getEventSetDescriptors():
返回 EventSetDescriptor 数组,描述 Bean 的事件集,包括事件类型、监听器接口等。
getDefaultEventSetDescriptors():
返回默认事件集描述符,通常用于 Bean 的主要事件。
readMethod 和 writeMethod 是 PropertyDescriptor 类的两个重要属性,它们用于描述 Java Bean 属性的 getter 和 setter 方法。这些方法是用于获取和设置 Bean 属性值的。
PropertyDescriptor 类
PropertyDescriptor 类在 java.beans 包中,提供了描述 Java Bean 属性的元数据。它包含了属性的名称、类型、getter 方法、setter 方法等信息。PropertyDescriptor 是 BeanInfo 中重要的一部分,用于 introspection 和 bean 属性管理。
readMethod
定义:readMethod 是 PropertyDescriptor 类的一个方法,表示用于读取(获取)属性值的 getter 方法。
类型:Method 类型。
用法:可以使用 getReadMethod() 方法获取与属性关联的 getter 方法。
writeMethod
定义:writeMethod 是 PropertyDescriptor 类的一个方法,表示用于写入(设置)属性值的 setter 方法。
类型:Method 类型。
用法:可以使用 getWriteMethod() 方法获取与属性关联的 setter 方法。
newInstance创建新对象
Java中new和newInstance的区别
创建方式:
new 关键字是编译时确定的创建对象方式,直接调用构造函数。
newInstance() 是通过反射在运行时动态创建对象的方式。
性能:
new 关键字性能更高,因为它是直接调用构造函数,没有额外的反射开销。
newInstance() 方法通常性能较低,因为需要通过反射查找和调用构造函数。
构造函数要求:
new 可以使用带有参数的构造函数。
newInstance() 方法仅能使用无参构造函数;如果类没有无参构造函数,则需要使用 Constructor 类的 newInstance() 方法来处理带参构造函数。
newInstance()方法相对于new的优点:
解耦合:通过工厂模式和反射机制实现对象创建的解耦合,降低了对具体类的依赖。
灵活性:允许在运行时动态决定要创建的对象类型,支持灵活的扩展和配置。
减少硬编码:通过配置文件或其他动态输入来决定要创建的对象,减少硬编码。
支持多种实现:可以根据不同的条件创建不同的实现类,支持多态性。
易于维护:对象创建逻辑集中管理,易于维护和修改。
<head> 用途:包含文档的元数据,如标题、字符集、链接、脚本等。
<title> 用途:定义网页的标题,显示在浏览器标签栏中。
<body> 用途:包含网页的内容,如文本、图像、链接等。
<h1> to <h6> 用途:定义标题,<h1> 为最高级标题,<h6> 为最低级标题。
<strong> 用途:定义加粗文本,表示重要性。
<a> 用途:定义超链接。
<ul> 用途:定义无序列表。
<ol> 用途:定义有序列表。
<table> 用途:定义表格。
<tr> 用途:定义表格行。
<th> 用途:定义表格头部单元格,内容通常加粗并居中。
<td> 用途:定义表格数据单元格。
<img>:<img src="image.jpg" alt="Description">
用途:插入图像。
</form>:
<form action="/submit" method="post">
<input type="text" name="name">
<input type="submit" value="Submit">
</form>
用途:定义表单。
<input>:
<input type="text" name="username">
<input type="password" name="password">
用途:定义输入控件。
<textarea>:<textarea rows="4" cols="50">Text area content</textarea>
用途:定义多行文本输入框。
<button>:<button type="button">Click Me</button>
用途:定义按钮。
<select>
<select name="options"> <option value="1">Option 1</option> <option value="2">Option 2</option> </select>
用途:定义下拉菜单。
<label>:
<label for="username">Username:</label>
<input type="text" id="username" name="username">
用途:定义表单控件的标签。
<header>:<header> <h1>Header Content</h1> </header>
用途:定义文档的头部区域。
<footer>:<footer><p>Footer Content</p></footer>
用途:定义文档的底部区域。
<article>:
<article> <h2>Article Title</h2> <p>Article content.</p> </article>
用途:定义独立的内容区域。
<main>:<main> <h1>Main Content</h1> </main>
用途:定义文档的主要内容区域。