什么是反射?
是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展
获取类对象:
类名.Class属性 ===》 person.Class; ===> Class aClass = Person.class;
对象名.getClass方法 ===》 person.getClass(); ===> Class aClass = person.getClass();
Class.forName(全类名)方法 ===》 Class aClass = Class.forName(“com.smiledog.fanshe.Person”); 主要使用
获取类对象的成员变量,构造函数,方法:
package com.smiledog.fanshe;
/*
@ClassName GetFanSheDemo
@Author SmILeDog
@Date 2021/5/12
@Time 12:52
通过获得类对象获取的对象的数据
*/
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class GetFanSheDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchFieldException {
//获取类实例
Class classzz = Class.forName("com.smiledog.fanshe.Person");
//获取类全路径
String name = classzz.getName();
//System.out.println(name);
//获取公开构造
Constructor[] cons1 = classzz.getConstructors();
for (Constructor con : cons1) {
System.out.println(con);
}
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//获取所有构造
Constructor[] cons2 = classzz.getDeclaredConstructors();
for (Constructor con : cons2) {
System.out.println(con);
}
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//获取指定参数构造
Constructor con1 = classzz.getConstructor(String.class);
System.out.println(con1);
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//获取公有方法
Method[] methods = classzz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//获取所有方法
Method[] declaredMethods = classzz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//获取指定方法名的方法
Method eat = classzz.getDeclaredMethod("eat");
System.out.println(eat);
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//获取公有成员变量
Field[] fields = classzz.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//获取所有成员变量
Field[] declaredFields = classzz.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//获取指定成员变量
Field name1 = classzz.getDeclaredField("name");
System.out.println(name1);
}
}
操作获取的类对象数据:
package com.smiledog.fanshe;
/*
@ClassName UseFanSheDemo
@Author SmILeDog
@Date 2021/5/12
@Time 14:55
通过获得类对象操作获取的对象的数据
*/
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class UseFanSheDemo {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class<?> classzz = Class.forName("com.smiledog.fanshe.Person"); //获取类对象
//使用构造方法
//Constructor<?> con1 = classzz.getDeclaredConstructor(String.class); //获取构造方法
//Object obj1 = con1.newInstance("10010"); //实例化对象
//System.out.println(obj1); //打印对象
//使用私有构造方法 不建议使用,既然是私有,强制反射的话出现安全问题
//Constructor<?> con2 = classzz.getDeclaredConstructor(int.class); //获取私有构造方法
//con2.setAccessible(true); //强制反射,,不加找不到私有构造,//不建议。。。。
//Object obj2 = con2.newInstance(100);
//System.out.println(obj2);
// //使用方法
// Object o = classzz.newInstance(); //实例化
// Method eatmethod = classzz.getMethod("eat"); //获取指定方法
// eatmethod.invoke(o); //调用指定对象的方法
// //使用私有方法
// Method showmethod = classzz.getDeclaredMethod("show"); //获取指定方法
// showmethod.setAccessible(true); //暴力反射
// showmethod.invoke(o); //调用指定对象的方法
//使用成员变量
// Object o = classzz.newInstance(); //实例化
// Field id = classzz.getField("id"); //获取指定成员变量
// id.set(o,"id:001"); //给指定对象赋值
// Object o1 = id.get(o); //获取指定对象的成员变量
// System.out.println(o1); //打印该对象
//使用私有成员变量
Object o = classzz.newInstance(); //实例化
Field name = classzz.getDeclaredField("name");//获取指定的私有成员变量
name.setAccessible(true); //强制反射该对象
name.set(o,"姓名:杀杀杀"); //给指定对象赋值
Object o1 = name.get(o); //获取指定对象的私有成员变量
System.out.println(o1); //打印该对象
}
}
反射&Properties案例:
package com.smiledog.fanshe.fanshedemo;
/*
@ClassName Person
@Author SmILeDog
@Date 2021/5/12
@Time 12:52
*/
public class Person {
public String id;
public String name;
public int age;
public void eat(){
System.out.println("干饭 .....");
}
public void sleep(){
System.out.println("碎觉 ......");
}
private void play(){
System.out.println("打豆豆 ......");
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package com.smiledog.fanshe.fanshedemo;
/*
@ClassName FanSheDemo
@Author SmILeDog
@Date 2021/5/12
@Time 15:54
使用properties配置文件,进行反射的相关操作
*/
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class FanSheDemo {
public static void main(String[] args) throws ClassNotFoundException, IOException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
FileReader fw = new FileReader(new File("person.properties"));
//day16/person.properties
//读取配置文件
Properties pro = new Properties();
pro.load(fw);
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
//反射
Class<?> aClass = Class.forName(className);
Object obj = aClass.newInstance();
Method method = aClass.getDeclaredMethod(methodName); //为避免获取私有方法,直接调用获取所有方法的方法
method.setAccessible(true); //且强制反射
method.invoke(obj);
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~person.properties~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
className=com.smiledog.fanshe.fanshedemo.Person
methodName=play
XML:
xml与html的区别:
html:用来展示数据的
xml:用来储存数据,持久化,配置文件【在网络中传输数据,后被json取代】
xml的基础语法:
1、xml文档的后缀名必须是:. xml
2、xml文档的第一行必须定义为:文档声明
3、xml文档有且仅有一个根标签
4、属性值必须使用引号(单引号或双引号)引起来
5、标签必须正确关闭,也就是双标签的规范
6、xml文档严格区分大小写
xml的快速入门:
使用xml描述学生信息:
<?xml version="1.0" encoding="utf-8" ?>
<!--This XML file does not appear to have any style information associated with it. The document tree is shown below.-->
<!--此XML文件似乎没有任何与之关联的样式信息。文档树如下所示。-->
<Students>
<student id="it001">
<name>张三</name>
<age>13</age>
<sex>男</sex>
</student>
<student id="it002">
<name>李四</name>
<age>14</age>
<sex>男</sex>
</student>
</Students>
xml的组成部分:
1、文档声明:
格式:
<?xml 属性列表 ?>
属性列表:
version:版本号:【1.0】
encoding:编码方式【默认值:ISO-8859-1】
standalone:是否独立【yes:不依赖其他文件 no:依赖其他文件】
2、指令:(不重要)
3、标签命名规则: (总之一句话:简洁明了)
名称可以包含字母,数字以及其他的字符
名称不能以数字或标点符号开始
名称不能以字母xml开始
名称不能包含空格
不要用 双引号,逗号,冒号,
xml命名经验之谈,文档经常有一个对应的数据库,最好根据数据库的命名规则来命名
4、属性:使用单引号和双引号
属性值唯一(官方说法)
5、文本:就是双标签里边的数据
转义字符:
<;:< 小于
>;:> 大于
&;:& 和
&apos;:’ ‘ 单引号
";:” “ 双引号
转成文本数据 :<![CDATA[ 文本内容 ]]>
xml的约束:
规定xml的书写规则
DTD约束:
新建一个文件,文件的扩展名是(.dtd)
<!ELEMENT students (student*) > //根标签下有一个或多个子标签
<!ELEMENT student (name,age,sex)> //子标签里边的子标签,且有顺序
<!ELEMENT name (#PCDATA)> //该标签中写文本
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ATTLIST student number ID #REQUIRED> //子标签的属性唯一
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE students SYSTEM "student.dtd">
<students>
<student number="001">
<name>张三</name>
<age>13</age>
<sex>男</sex>
</student>
</students>
Schema约束:
新建一个文件,文件的扩展名是:(.xsd)
<?xml version="1.0"?>
<xsd:schema xmlns="(命名空间:公司域名)/xml"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" //固定写法
targetNamespace="(命名空间:公司域名)/xml" elementFormDefault="qualified">
<xsd:element name="students" type="studentsType"/>
<xsd:complexType name="studentsType">
<xsd:sequence>
<xsd:element name="student" type="studentType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="studentType">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/> //指定类型
<xsd:element name="age" type="ageType" /> //自定义类型
<xsd:element name="sex" type="sexType" />
</xsd:sequence>
<xsd:attribute name="number" type="numberType" use="required"/>
</xsd:complexType>
<xsd:simpleType name="sexType"> //自定义类型的格式
<xsd:restriction base="xsd:string"> //自定义类型内容的类型
<xsd:enumeration value="male"/> //指定内容范围 :单选
<xsd:enumeration value="female"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ageType"> //自定义类型的格式
<xsd:restriction base="xsd:integer"> //自定义类型内容的类型
<xsd:minInclusive value="0"/> //指定内容范围 :数值范围
<xsd:maxInclusive value="100"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="numberType"> //自定义类型的格式
<xsd:restriction base="xsd:string"> //自定义类型内容的类型
<xsd:pattern value="itfxp_\d{4}"/> //正则表达式 :内容格式:(itfxp_开头 加上 四位数)
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<?xml version="1.0" encoding="UTF-8" ?>
<!--
1.填写xml文档的根元素
2.引入xsi前缀. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" //固定写法
3.引入xsd文件命名空间. xsi:schemaLocation="(命名空间:公司域名)/xml student.xsd"
4.为每一个xsd约束声明一个前缀,作为标识 xmlns="(命名空间:公司域名)"
-->
<students xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="(命名空间:公司域名)"
xsi:schemaLocation="(命名空间:公司域名)/xml student.xsd"
>
<student number="itfxp_0010">
<name>张三</name>
<age>100</age>
<sex>male</sex>
</student>
</students>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~