《反射+xml+注解》
创始人
2025-05-28 08:58:32

反射

反射(Reflection)是java程序开发语言的特征之一,它允许运行中的java对自身进行检查

反射就是把java类中的各种成分映射成一个个的java对象

加载的时候 : Class对象的由来是将.class文件读入内存,并为之创建一个Class对象

java反射机制,可以实现一下功能

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

获取源头Class

所有类的对象其实都是Class的实例

获取类的Class对象

  1. Class.forName(“包名.类名”)
  2. 类.class
  3. 对象.getClass()

获取Class对象

Class是一切反射的源头

  1. 第一种对象.class
    Source s=new Source();
    Classc1=s.getClass();
    System.out.println(c1.getName());

  2. 第二种类.class
    Classc2=Source.class;
    System.out.println(c2.getName());

  3. 第三种Class.forname
    Class c3=Class.forName(“com.shsxt.ref.simple.Source”);
    System.out.println(c3.getName());

获取修饰符

获取修饰符,使用 getModifiers() 即可, Modifier 类提供了 static 方法和常量来解码类和成员访问修饰符

方法 :

int getModifiers() 返回此类或接口的Java语言修饰符,以整数编码。

代码 :

Classclz=Class.forName(“com.shsxt.ref.simple.User”);
//获得修饰符
int n=clz.getModifiers();
//使用Modifier转换为相应的字符串
System.out.println(Modifier.toString(n));

父类与接口

方法:

[] getInterfaces() 返回由此对象表示的类或接口直接实现的接口。

getSuperclass() 返回 类表示此所表示的实体(类,接口,基本类型或void)的直接超类 类 。

代码

//类 getSuperclass() 返回 类表示此所表示的实体(类,接口,基本类型或void)的直接超类 类 。
Class superClass = cls.getSuperclass();
System.out.println(superClass);
System.out.println(superClass==Object.class);

    //类[] getInterfaces() 返回由此对象表示的类或接口直接实现的接口。Class[] arr = cls.getInterfaces();System.out.println(Arrays.toString(arr));

属性和方法

属性

获取所有属性(包括父类或接口) ,使用 Field 即可操作, Field 作为描述属性的对象

方法

字段 getField(String name) 返回 字段对象,该对象反映此 类对象表示的类或接口的指定公共成员字段。

字段[] getFields() 返回一个包含 字段对象的数组, 字段对象反映此 类对象所表示的类或接口的所有可访问公共字段。

字段 getDeclaredField(String name) 返回 字段对象,该对象反映此 类对象表示的类或接口的指定声明字段。

字段[] getDeclaredFields() 返回 字段对象的数组, 字段对象反映由此 类对象表示的类或接口声明的所有字段。

学生类 :

package fanshe.field;
public class Student {
public Student(){

}
//**********字段*************//
public String name;
protected int age;
char sex;
private String phoneNum;@Override
public String toString() {return "Student [name=" + name + ", age=" + age + ", sex=" + sex+ ", phoneNum=" + phoneNum + "]";
}

}

测试类

package fanshe.field;
import java.lang.reflect.Field;
public class Fields {

	public static void main(String[] args) throws Exception {//1.获取Class对象Class stuClass = Class.forName("fanshe.field.Student");//2.获取字段System.out.println("************获取所有公有的字段********************");Field[] fieldArray = stuClass.getFields();for(Field f : fieldArray){System.out.println(f);}System.out.println("************获取所有的字段(包括私有、受保护、默认的)********************");fieldArray = stuClass.getDeclaredFields();for(Field f : fieldArray){System.out.println(f);}System.out.println("*************获取公有字段**并调用***********************************");Field f = stuClass.getField("name");System.out.println(f);//获取一个对象Object obj = stuClass.getConstructor().newInstance();//产生Student对象--》Student stu = new Student();//为字段设置值f.set(obj, "刘德华");//为Student对象中的name属性赋值--》stu.name = "刘德华"//验证Student stu = (Student)obj;System.out.println("验证姓名:" + stu.name);System.out.println("**************获取私有字段****并调用********************************");f = stuClass.getDeclaredField("phoneNum");System.out.println(f);f.setAccessible(true);//解除私有限定f.set(obj, "18888889999");System.out.println("验证电话:" + stu);}
}

方法

获取所有方法(包括父类或接口),使用 Method 即可。 Method 即作为描述方法的对象。

方法

方法 getDeclaredMethod​(String name, 类… parameterTypes) 返回 方法对象,该对象反映此 类对象表示的类或接口的指定声明方法。

方法[] getDeclaredMethods() 返回一个包含 方法对象的数组, 方法对象反映此 类对象表示的类或接口的所有已声明方法,包括public,protected,default(package)访问和私有方法,但不包括继承的方法。

方法 getMethod(String name, 类… parameterTypes) 返回 方法对象,该对象反映此 类对象表示的类或接口的指定公共成员方法。
方法[] getMethods() 返回一个包含 方法对象的数组, 方法对象反映此 类对象所表示的类或接口的所有公共方法,包括由类或接口声明的那些以及从超类和超接口继承的那些。

学生类

package fanshe.method;

public class Student {
//成员方法*//
public void show1(String s){
System.out.println("调用了:公有的,String参数的show1(): s = " + s);
}
protected void show2(){
System.out.println(“调用了:受保护的,无参的show2()”);
}
void show3(){
System.out.println(“调用了:默认的,无参的show3()”);
}
private String show4(int age){
System.out.println("调用了,私有的,并且有返回值的,int参数的show4(): age = " + age);
return “abcd”;
}
}

测试类

public class MethodClass {

public static void main(String[] args) throws Exception {//1.获取Class对象Class stuClass = Class.forName("fanshe.method.Student");//2.获取所有公有方法System.out.println("***************获取所有的”公有“方法*******************");stuClass.getMethods();Method[] methodArray = stuClass.getMethods();for(Method m : methodArray){System.out.println(m);}System.out.println("***************获取所有的方法,包括私有的*******************");methodArray = stuClass.getDeclaredMethods();for(Method m : methodArray){System.out.println(m);}System.out.println("***************获取公有的show1()方法*******************");Method m = stuClass.getMethod("show1", String.class);System.out.println(m);//实例化一个Student对象Object obj = stuClass.getConstructor().newInstance();m.invoke(obj, "刘德华");System.out.println("***************获取私有的show4()方法******************");m = stuClass.getDeclaredMethod("show4", int.class);System.out.println(m);m.setAccessible(true);//解除私有限定Object result = m.invoke(obj, 20);//需要两个参数,一个是要调用的对象(获取有反射),一个是实参System.out.println("返回值:" + result);}

}

setAccessible(true):接触私有限定

创建对象

根据Class对象,我们可以获得构造器,为实例化对象做准备。

Class–>newInstance 创建Class对象所有表示类型的的实例–>默认调用空构造

//Class对象
Class cls = ClassEmp.class;

    //1.创建对象  Class-->newInstanceClassEmp emp = cls.newInstance();System.out.println(emp);
  1. 调用类对象的构造方法

员工类

public class ClassEmp {
private String name;
private int age;
private int id;

public ClassEmp() {
}public ClassEmp(String name, int age, int id) {this.name = name;this.age = age;this.id = id;
}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;
}@Override
public boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;ClassEmp classEmp = (ClassEmp) o;return age == classEmp.age &&id == classEmp.id &&Objects.equals(name, classEmp.name);
}@Override
public int hashCode() {return Objects.hash(name, age, id);
}@Override
public String toString() {return "ClassEmp{" +"name='" + name + '\'' +", age=" + age +", id=" + id +'}';
}

}

测试类

//2创建构造器
Class cls = ClassEmp.class;
Constructor[] cons = cls.getConstructors();
Arrays.stream(cons).forEach(System.out::println);

Constructorcon=cls.getDeclaredConstructor(String.class,int.class,int.class);
System.out.println(con);

注意 : newInstance()是调用空构造,如果空构造不存在,会出现异常

类加载器

什么是类加载器

类加载器(class loader)用来加载java类到java虚拟机中

系统提供的类jiazaiqi1

  1. 引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。
  2. 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
  3. 系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。

类的声明周期

类的加载是通过类加载器完成的的,加载器将 .class 文件的二进制文件装入JVM的方法区,并且在堆区创
建描述这个类的 java.lang.Class 对象。用来封装数据。 但是同一个类只会被类装载器装载一次。
链接就是把二进制数据组装为可以运行的状态。链接分为校验,准备,解析这3个阶段

  1. 校验一般用来确认此二进制文件是否适合当前的JVM(版本)
  2. 准备就是为静态成员分配内存空间。并设置默认值
  3. 解析指的是转换常量池中的代码作为直接引用的过程,直到所有的符号引用都可以被运行程序使用(建立完整的对应关系)完成之后,类型也就完成了初始化,初始化之后类的对象就可以正常使用了,直到一个对象不再使用之后,将在适当的实际被GC回收。释放空间。当没有任何引用指向Class对象时就会被卸载,结束类的生命周期

类加载器

类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance() 方法就可以创建出该类的一个对象。实际的情况可能更加复杂

java中三中类类加载器

  1. Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。
  2. Extension ClassLoader 用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类
  3. AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。 了解
    即可。

public static void main(String[] args) throws Exception {
System.out.println("类加载器
"+ClassLoader.class.getClassLoader().getClass().getName());
}

XML
可扩展的标记语言
版本声明

必须存在于cml文件的首行

作用
传输,存储,配置,解析
语法
语言要求严谨,必须严格按照语法进行定义

标签分类

  1. 双标签
  2. 单标签

属性

更完整的展示标签的作用

基础语法

XMl文档形成了一种树结构,它从"根部"开始,然后扩展到"枝叶"

17 汪小仔

格式良好的XML文档需要满足一下条件

  1. 必须有XML声明语句 (第一行)
  2. 必须有且仅有一个根元素
  3. 标签成对
  4. 元素正确嵌套

实体

实体是对数据的引用;根据实体种类的不同,XML 解析器将使用实体的替代文本或者外部文档的内容来
替代实体引用。

xml中,一些字符拥有特殊的意义。如果把字符 < 放在xml元素中,会发生错误,这是因为解析器会把它当作新元素的开始,这样会产生xml错误

约束

“形式良好”或“结构良好”的 XML 文档拥有正确的语法。合法的 XML 文档是“形式良好”的 XML 文档,并且遵循了特定的约束。

在XML技术里,可以编写一个文档来约束一个XML文档的书写规范(与xml语法无关),这称之为XML约束。此举主要是为了保证数据的规范性和安全性。

DTD约束 : 语法简洁 : 功能比较单一

Schema约束:语法复杂,功能比较强大。

DTD

DTD即文档类型定义-- Document Type Definition

一个DTD文档可能包含如下内容

  1. 元素的定义规则
  2. 元素之间的关系规则
  3. 属性的定义规则

内部约束

DTD约束和xml写在一个文件中。

语法

]>

王维

鹿柴 空山不见人,但闻人语声。返景入深林,复照青苔上。

外部导入

当验证的XML文件较多时,使用内部DTD可能出现冗余,此时可以通过引入dtd 文件进行xml 约束。

SYSTEM本地文件系统

PUBLIC DTD文件为网络文件,url

Schema

Schema是用一套预先规定的xml元素和属性创建的,这些元素和属性定义了xml文档的结构和内容模式。Xml Shema规定xml文档实例的结构和每个元素/属性的数据类型。

XML解析

xml解析即将文件中的内容按照指定 的含义进行获取

Dom4J解析Xml

解析scores.xml文档

scores.xml
张三20180010113
上海外国语
123456
王五20180020114
上海外国语
657432
获取document对象SAXReader reader=new SAXReader();
Document document=reader.read(new File("input.xml"));操作xml文档节点Element rootElm=document.getRootElement();//获得根节点
Element memberElm=root.element("member"); //获得子节点
String text=memberElm.getText();//获得节点文本
Element ageElm=newMemberElm.addElement("age");//添加子节点
ageElm.setText("29");//设置节点文本
parentElm.remove(childElm);//)删除某节点例子public static void main(String[] args) throws Exception{SAXReader reader=new SAXReader();Document document=reader.read(new 			    	File("src\\source.xml"));Element rootElm=document.getRootElement();//获得根节点Element memberElm=rootElm.element("Student"); //获得子节点Element ageElm=memberElm.addElement("age");//添加子节点ageElm.setText("29");//设置节点文本
// 创建格式化类OutputFormat format = 			      		    	OutputFormat.createPrettyPrint();
// 设置编码格式,默认UTF-8format.setEncoding("UTF-8");
// 创建输出流,此处要使用Writer,需要指定输入编码格式,使用OutputStream则不用FileOutputStream fos = new 			   FileOutputStream("src\\source.xml");
// 创建xml输出流XMLWriter writer = new XMLWriter(fos, format);writer.write(document);
writer.close();
}

注解

jdk1.5新增–> 标注

作用

  1. 注释
  2. 强制检查作用
  3. 配置注解时候,可以同时传递参数,执行过程中可以通过反射获取所配置的数据进行使用
  4. 可以存在与编译后的class文件中
  5. 大量的代替了配置文件

语法

@注解名(参数)–不需要参数可以省略()

位置

可以定义在任意位置,可以通过Targee规定注解的使用位置

分类

  1. 根据参数个数划分
    a. 标记注解:没有参数
    b. 单值注解:参数有一个
    c. 完整注解:多个参数
  2. jdk内置注解
    a. 普通注解:注解其他内容
    ⅰ. @Override 限定重写父类方法
    ⅱ. @Deprecated 标记已过时
    ⅲ. @SuppressWarnings 抑制编译器警告,该注解仅仅告知编译器,而忽略他们产生了特殊警告
    ⅳ. @FunctionalInterface 标记函数式接口
    b. 元注解:注解注解的注解
    ⅰ. @Target 用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
    ⅱ. @Retention 表示需要在什么级别保存该注释信息,用于描述注解的生命周期
    ⅲ. @Documented 表示使用该注解得元素应该被javadoc或类似工具文档化
    ⅳ. @Inherited 表示一个注解类型会被自动继承
    ⅴ. @Repeatable 某些情况下,一个程序元素需要使用多个同一种类型的注解
    3.自定义注解
    a. @interface定义注解类型
    b. 默认隐式的实现了java.lang.anntotion.Annotation接口 所有注释类型扩展的公共接口
    c. 自定义的注解类型不能显示的实现其他接口继承其他父类
    d. 如果定义注解类型中定义了字段,使用注解类型时必须配置参数为字段赋值
    e. 注解类型中的字段:数据类型 字段名();
    f. 数据类型只能为:基本数据类型 字符串 注解类型 枚举类型 以上类型的数组
    g. 如果注解类型中字段只有一个,建议字段名为value,在传递实参时候,可以直接赋值
    h. 如果注解类型中存在字段,可以通过default为字段设置默认值

相关内容

热门资讯

〖重大通报〗“欢聚麻将究竟怎么... 【无需打开直接搜索微信【4579337】操作使用教程:1.亲,实际上欢聚麻将是可以开挂的,确实有挂....
实测分享“新人皇斗牛透视辅助软... 您好:新人皇斗牛这款游戏可以开挂,确实是有挂的,需要软件加微信【4770480】,很多玩家在新人皇斗...
盘点一款!玩几局怎么开挂!太坑... 您好:玩几局这款游戏可以开挂,确实是有挂的,需要了解加客服微信【9183893】很多玩家在这款游戏中...
实测建议( 大金牙麻将真的可以... 您好:大金牙麻将这款游戏是可以开挂的,究竟有没有挂确实能开挂,了解请添加《3045033》(加我们微...
〖实测分享〗“攸乐碰胡怎么装挂... 您好:【攸乐碰胡】这款游戏可以开挂,确实是有挂的,需要了解加客服微信【7482525】很多玩家在这款...