JavaSE(十四) --- <补充知识点> [XML文件,反射]
Posted 小智RE0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaSE(十四) --- <补充知识点> [XML文件,反射]相关的知识,希望对你有一定的参考价值。
XML文件
xml文件是可扩展性标记语言,是用来存储,传输数据的
;
而html作为超文本标记语言 (HyperText Markup Language);是用来显示数据的.
缺点就是xml的语法比较繁琐,早期还是要用Java语言解析xml文件,读写数据.
XML能对各种编程语言编写的数据进行管理,使得在任何平台下都能通过解析器来读取XML数据。
XML的命名规则
(1)名称没有字符限制,数字字母字符都可以用(没有保留字这个说法),但是不能以数字或者标点符号,或者以字符 “xml”(或者 XML、Xml)
开始
(2)写名称不能包含空格;
就从Tomcat的web.xml配置文件来看吧
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
</web-app>
XML 主要分为4个部分,
文档声明
声明文件的可选部分,若存在需要放在文档的第一行
<?xml version="1.0" encoding="UTF-8"?>
元素(标签)
注意只能有一个根元素
;元素中可嵌套其他元素,也可以出现空元素
(即只写标签,内部不写内容)
需要注意的是,写的标签必须要闭合;
标签对大小写敏感
比如说,我在自定义xml文件时,上面开始写了一个根元素
users
,但是下面又写出一个根元素,出现错误提示Multiple root tags(多个根标签)
属性
属性是修饰元素的.
如果要在一个元素写比较多的属性时,注意属性名不要相同.
在写属性值的时候,记着别写 & 或者 ' 或者<
;而且属性值一定要用双引号或者单引号包括起来
;
比如说,我在同一个标签name内写了两个属性名相同的属性word,诶,就出现错误了.
提示Duplicate attribute word(重复属性词)
注释
注释使用<!---->
;对需要说明的地方,写上自己的解释.
XML的语法规则
首先需要注意的是,不要随意留空格,空格会被保留;
在 XML 中,有 5 个预定义的实体引用:
引用 | 表示 | 含义 |
---|---|---|
< | < | 小于 (less than) |
> | > | 大于 (greater than) |
& | & | 和 (ampersand) |
' | ’ | 单引号 (apostrophe) |
" | " | 双引号 (quotation mark) |
XML约束
可以写一个文档约束对xml的书写规范进行约束,
- DTD约束:语法相对简单,功能简单。学习成本低。
- Schema约束:语法相对复杂,功能强大。学习成本高.
而Tomcat的xml约束就是Schema约束;
反射
在之前需要获取一个类的对象时,首先需要设计定义一个类,然后才用new+构造方法的方式创建类的对象;然后才能通过对象去调用类的属性或方法.
但是这样的方式不太灵活
反射
而反射机制只需要类名就能动态获取得到类的信息,类的对象
实际上,在之前学习时也是接触过反射的;
比如说,在web.xml配置文件中配置servlet时,当时是通过类名获取到定义的servlet类信息
实际可理解为;先解析xml文件;然后读取到类的地址,根据类的地址,通过反射机制获取类的对象.
第二个情况就是在学习Jdbc时,加载类的机制就是用了反射.
Class.forName(“com.mysql.cj.jdbc.Driver”);
反射的理解
每当使用一个类时,类加载器就把类的字节码信息读取到内存中,并且为每个类创建一个class类的对象,通过Class对象即可获取类的信息.
练习时使用的实体类Person
public class Person {
public String name;
private int age;
private int id;
public Person(){
System.out.println("无参构造方法");
}
public Person(String name,int id,int age){
this.name=name;
this.age=age;
this.id=id;
System.out.println("有参构造方法-->name-->id-->age");
}
private Person(int age){
System.out.println("私有构造方法-->id");
}
public void run(){
System.out.println("run方法");
}
public void run(String name){
System.out.println("run方法-->name");
}
private void run(String name,int age){
System.out.println("私有修饰run方法-->name-->age");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
获取Class类对象的三种方式
(1) 类名.class的方式
//方式1:直接用类名.class的方式;
Class person1 = Person.class;
System.out.println(person1);
返回
class com.xiaozhi.pojo.Person
(2)使用Object类的getClass()方法
//方式2;先获取到Person类的对象,然后使用getClass方式获取;
Person p=new Person();
Class person2 = p.getClass();
System.out.println(person2);
返回
无参构造方法
class com.xiaozhi.pojo.Person
(3)通过Class类的forName(String name)方法
//方式3:通过Class类的forName方法;前提是需要知道类的路径地址;
//根据Person类的地址,将类的信息加载到内存中,然后获得Class的对象;可动态操作类的信息;
Class person3 = Class.forName("com.xiaozhi.pojo.Person");
System.out.println(person3);
返回
class com.xiaozhi.pojo.Person
其实,这几种方式获取到的是一样的
获取类的构造方法信息
😃(1)Class类的 getConstructor()
方法可获取公共的无参构造方法
public Constructor getConstructor(Class<?>… parameterTypes) throws NoSuchMethodException, SecurityException
Constructor类的 newInstance()
方法也可以为类创建对象;
public Object newInstance(Object… initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, reflect.InvocationTargetException
练习
//通过Class类的forName方法;前提是需要知道类的路径地址;
Class person = Class.forName("com.xiaozhi.pojo.Person");
//Class类的 getConstructor() 方法;获取公共的无参构造方法;
Constructor constructor = person.getConstructor();
System.out.println(constructor);
//Constructor类的 newInstance 可为类创建对象;
Person p=(Person)constructor.newInstance();
System.out.println(p);
输出:
public com.xiaozhi.pojo.Person()
无参构造方法
com.xiaozhi.pojo.Person@74a14482
😃(2)Class类的getConstructor(Class<?>... parameterTypes)
方法;获取公共的指定参数列表的有参构造方法
;
public Constructor getConstructor(Class<?>… parameterTypes) throws NoSuchMethodException, SecurityException
练习
//通过Class类的forName方法;前提是需要知道类的路径地址;
Class person = Class.forName("com.xiaozhi.pojo.Person");
//Class类的getConstructor(Class<?>... parameterTypes)方法;获取公共的指定参数列表的有参构造方法;
Constructor constructor = person.getConstructor(String.class,int.class,int.class);
System.out.println(constructor);
//根据得到的构造方法创建对象;
Person p=(Person)constructor.newInstance("小智",21,178);
System.out.println(p);
输出:
public com.xiaozhi.pojo.Person(java.lang.String,int,int)
有参构造方法-->name-->id-->age
com.xiaozhi.pojo.Person@74a14482
😃(3)Class类的getConstructors()
方法;获取所有公共的构造方法
;
public Constructor<?>[] getConstructors() throws SecurityException
练习:
//Class类的getConstructors() 方法;获取所有公共的构造方法;
Constructor[] constructors = person.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
输出:
public com.xiaozhi.pojo.Person(java.lang.String,int,int)
public com.xiaozhi.pojo.Person()
😃(4)Class类的getDeclaredConstructor(Class<?>... parameterTypes)
方法,获取指定参数列表的构造方法
;包括私有修饰的构造方法
public Constructor getDeclaredConstructor(Class<?>… parameterTypes) throws NoSuchMethodException, SecurityException
练习
//通过Class类的forName方法;前提是需要知道类的路径地址;
Class person = Class.forName("com.xiaozhi.pojo.Person");
//Class类的getDeclaredConstructor(Class<?>... parameterTypes) 获取指定参数列表的构造方法;
Constructor declaredConstructor = person.getDeclaredConstructor(String.class,int.class,int.class);
System.out.println(declaredConstructor);
Constructor declaredConstructor1 = person.getDeclaredConstructor(int.class);
System.out.println(declaredConstructor1);
输出
public com.xiaozhi.pojo.Person(java.lang.String,int,int)
private com.xiaozhi.pojo.Person(int)
但是呢,拿到私有修饰的构造方法时,就需要解决权限问题;
//通过Class类的forName方法;前提是需要知道类的路径地址;
Class person = Class.forName("com.xiaozhi.pojo.Person");
//涉及到私有修饰的方法时;
Constructor declaredConstructor1 = person.getDeclaredConstructor(int.class);
Person p= (Person) declaredConstructor1.newInstance(21);
System.out.println(p);
出现异常;提示IllegalAccessException
没有访问权限.
Exception in thread “main” java.lang.IllegalAccessException: Class com.xiaozhi.pojo.Test2 can not access a member of class com.xiaozhi.pojo.Person with modifiers “private”
那么就去设置手动打开权限;
在Constructor
类有这样一个父类AccessibleObject
有这样的一个方法setAccessible(boolean flag)
可以设置是否检查访问权限;默认为false
true的值表示反射对象应该在使用时抑制Java语言访问检查。 false的值表示反映的对象应该强制执行Java语言访问检查。
那就试试吧
//涉及到私有修饰的方法时;
Constructor declaredConstructor1 = person.getDeclaredConstructor(int.class);
//拒绝权限检查;
declaredConstructor1.setAccessible(true);
Person p= (Person) declaredConstructor1.newInstance(21);
System.out.println(p);
输出
私有构造方法-->id
com.xiaozhi.pojo.Person@74a14482
😃(5) Class类的getDeclaredConstructors()
获取所有的构造方法
public Constructor<?>[] getDeclaredConstructors() throws SecurityException
练习
//通过Class类的forName方法;前提是需要知道类的路径地址;
Class person = Class.forName("com.xiaozhi.pojo.Person");
//Class类的getDeclaredConstructors() 获取所有的构造方法
Constructor[] declaredConstructors = person.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
输出
private com.xiaozhi.pojo.Person(int)
public com.xiaozhi.pojo.Person(java.lang.String,int,int)
public com.xiaozhi.pojo.Person()
获取类的 属性; 和 方法
(1)Class类的getFields()
方法; 获取所有公共属性
;
public Field[] getFields() throws SecurityException
Filed类的 getName()方法
;获取属性名;
public String getName()
Filed类的get(对象)方法
;获取属性值;
public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException
练习
//通过Class类的forName方法;前提是需要知道类的路径地址;
Class person = Class.forName("com.xiaozhi.pojo.Person");
//先用构造方法创建一个对象;
Constructor declaredConstructor = person.getConstructor();
Person p= (Person) declaredConstructor.newInstance();
//Class类的 getFields() 方法获取所有公共属性;
Field[] fields = person.getFields();
for (Field field : fields) {
//Filed类的 getName()方法;获取属性名;
System.out.println("Person类的属性=>"+field.getName());
//Filed类的 get(对象)方法;获取属性值;
System.out.println("Person类的属性值=>"+field.get(p));
}
输出;
无参构造方法
Person类的属性=>name
Person类的属性值=>null
(2)Class类的getDeclaredFields()
方法; 获取所有属性
; 包括私有修饰的属性
public Field[] getDeclaredFields() throws SecurityException
练习
//通过Class类的forName方法;前提是需要知道类的路径地址;
Class person = Class.forName("com.xiaozhi.pojo.Person");
//先用构造方法创建一个对象;
Constructor declaredConstructor = person.getDeclaredConstructor(String.class,int.class,int.class);
Person p= (Person) declaredConstructor.newInstance("小智",21,178);
//Class类的 getDeclaredFields() 方法获取所有属性;
Field[] fields = person.getDeclaredFields();
for (Field field : fields) {
//需要开启权限;
field.setAccessible(true);
//Filed类的 getName()方法;获取属性名;
System.out.println("Person类的属性=>"+field.getName());
//Filed类的 get(对象)方法;获取属性值;
System.out.println("Person类的属性值=>"+field.get(p));
}
输出
有参构造方法-->name-->id-->age
Person类的属性=>name
Person类的属性值=>小智
Person类的属性=>age
Person类的属性值=>21
Person类的属性=>id
Person类的属性值=>178
(3)Class类的 getDeclaredMethod()
方法 获取指定名称,指定参数列表的方法
public Method getDeclaredMethod(String name, Class<?>… parameterTypes) throws NoSuchMethodException, SecurityException
练习
//通过Class类的forName方法;前提是需要知道类的路径地址;
Class person = Class.forName("com.xiaozhi.pojo.Person");
// Class类的 getDeclaredMethod 方法 获取指定名称,指定参数列表的方法
Method run = person.getDeclaredMethod("run",String.class,int.class);
System.out.println(run);
输出
private void com.xiaozhi.pojo.Person.run(java.lang.String,int)
(4)Class类的 getDeclaredMethods()
方法,获取所有方法;
public Method[] getDeclaredMethods() throws SecurityException
练习
//通过Class类的forName方法;前提是需要知道类的路径地址;
Class person = Class.forName("com.xiaozhi.pojo.Person");
//Class类的 getDeclaredMethods() 方法,获取所有方法;
Method[] methods = person.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
输出
private void com.xiaozhi.pojo.Person.run(java.lang.String,int)
public void com.xiaozhi.pojo.Person.run(java.lang.String)
public void com.xiaozhi.pojo.Person.run()
public java.lang.String com.xiaozhi.pojo.Person.getName()
public int com.xiaozhi.pojo.Person.getId()
public void com.xiaozhi.pojo.Person.setName(java.lang.String)
public void com.xiaozhi.pojo.Person.setId(int)
public int com.xiaozhi.pojo.Person.getAge()
public void com.xiaozhi.pojo.Person.setAge(int)
以上是关于JavaSE(十四) --- <补充知识点> [XML文件,反射]的主要内容,如果未能解决你的问题,请参考以下文章