JAVASE18
一、反射
程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言,如Python,Ruby是动态语言;显然C++,Java,C#不是动态语言,但是JAVA有着一个非常突出的动态相关机制:Reflection。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个
对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为
java语言的反射机制,很多优秀的开源框架都是通过反射完成的。
发生在程序运行期间的行为
java不是动态语言,存在一个动态机制->反射机制
在一个类型加载到内存中的时候,就会存在一个当前类型的Class对象
Class对象是唯一的,不变的
创建的对象都是Class对象的镜像
Class对象中包含这个类中的所有内容,所以反射的源头是Class对象
反射的源头: Class类型的对象
Class 类 类类实例表示正在运行的Java应用程序中的类和接口。
注意:
反射大量的应用在框架,组件,服务器…等的底层存在
public class ReflectDemo01 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, IOException {
Properties pro = new Properties();
pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("classname.properties"));
//通过反射创建对象
Person p = (Person) Class.forName(pro.getProperty("classname")).newInstance();
p.eat();
}
}
class Person{
void eat(){
System.out.println("用手吃饭");
}
}
class Student extends Person{
void eat(){
System.out.println("用笔吃饭");
}
}
class Coder extends Person{
void eat(){
System.out.println("用代码吃饭");
}
}
①获取反射的源头class对象
1.类名.class
2.对象.getClass()
3.Class.forName(“包名.类名”) -->推荐
public static void main(String[] args) throws ClassNotFoundException {
// 1.类名.class
Class<String> cls1 = String.class;
System.out.println(cls1.toString());
//2.对象.getClass()
Class cls2 = "".getClass();
System.out.println(cls2);
System.out.println(cls1==cls2);
// 3.Class.forName("包名.类名")
Class cls3 = Class.forName("java.lang.String");
System.out.println(cls3);
System.out.println(cls3.getName());
System.out.println(cls3.getSimpleName());
System.out.println(cls3.isPrimitive());
System.out.println(cls3.getSuperclass());
System.out.println(Arrays.toString(cls3.getInterfaces()));
//基本数据类型的Class对象
System.out.println(int.class);
System.out.println(Integer.TYPE); //获取对应基本数据类型的class对象
System.out.println(Integer.class);
System.out.println(int.class == Integer.class);
System.out.println(int.class == Integer.TYPE);
}
②通过反射创建对象
1.Class类的T newInstance() 已过时。 方法 创建当前Class对象所表示类型的对象
默认调用空构造
2.获取指定的构造器,然后创建对象使用指定构造器为对象初始化信息
1)获取类中所有的构造器|指定的某一个构造器
构造器 getConstructor(类<?>… parameterTypes) 返回一个 构造器对象,该对象反映此 类对象所表示的类的指定公共构造函数。
构造器<?>[] getConstructors()返回全部公共的构造器对象,
构造器 getDeclaredConstructor(类<?>… parameterTypes) 返回一个 构造器对象,该对象反映此 类对象所表示的类或接口的指定构造函数。
构造器<?>[] getDeclaredConstructors() 返回 构造器对象的数组, 构造器对象反映由此 类对象表示的类声明的所有构造函数。
2.创建对象,指定使用这个构造器
T newInstance(Object… initargs)
public class ReflectDemo {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//1.获取Goods类型的Class对象
Class<Goods> cls = Goods.class;
//2.newInstance() 被弃用不推荐
Goods good = cls.newInstance();
System.out.println(good);
//3. 1)获取构造器
Constructor[] cons = cls.getConstructors();
for(Constructor con:cons){
System.out.println(con+"---->参数个数:"+con.getParameterCount());
}
//getDeclaredConstructor(类<?>... parameterTypes)
Constructor con = cls.getDeclaredConstructor(int.class);
System.out.println(con);
//私有内容无权访问-->忽略权限
con.setAccessible(true); //忽略权限
//2.创建对象
Goods g = (Goods) con.newInstance(101);
System.out.println(g);
//获取修饰符
System.out.println(con.getModifiers());
//修饰符的字符串表现形式
System.out.println(Modifier.toString(con.getModifiers()));
}
}
//商品
class Goods{
private int no;
private String name;
//构造器
public Goods() {
}
private Goods(int no) {
this.no = no;
}
public Goods(int no, String name) {
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "Goods{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
}
③通过反射操作属性
-
Class对象
-
获取某一个类型的属性
字段 getField(String name) 返回 字段对象,该对象反映此 类对象表示的类或接口的指定公共成员字段。
字段[] getFields()
字段 getDeclaredField(String name) 返回 字段对象,该对象反映此 类对象表示的类或接口的指定声明字段。
字段[] getDeclaredFields() -
操作属性
void set(Object obj, Object value)
Object get(Object obj) 返回指定对象上此 字段表示的字段的值。
public class ReflectDemo04 {
public static void main(String[] args) throws Exception {
testField(Shopping.class);
}
public static void testField(Class<Goods> cls) throws Exception {
// 1) Class对象
// 2) 获取某一个类型的属性
Field filed = cls.getDeclaredField("name");
//忽略权限
filed.setAccessible(true);
//对象
Shopping shop= cls.getConstructor(int.class,String.class).newInstance(111,"zhizihua");
System.out.println(shop);
// 3) 操作属性
filed.set(shop,"栀子花");
System.out.println(shop);
System.out.println(filed.get(shop));
//类<?> getType() 返回 类对象,该对象标识此 字段对象表示的字段的声明类型。
System.out.println(filed.getType());
}
}
④反射操作方法
1.获取方法
方法 getMethod(String name, 类<?>… parameterTypes) 返回 方法对象,该对象反映此 类对象表示的类或接口的指定公共成员方法。
方法[] getMethods()
方法 getDeclaredMethod(String name, 类<?>… parameterTypes) 返回 方法对象,该对象反映此 类对象表示的类或接口的指定声明方法。
方法[] getDeclaredMethods()
2.操作方法
Object invoke(Object obj, Object… args)
返回值为: 调用执行的方法的返回值,如果没有,返回null
public class ReflectDemo05 {
public static void main(String[] args) throws Exception {
testMethod(Goods.class);
}
/*
获取方法
*/
public static void testMethod(Class<Goods> cls) throws Exception {
//可以获取到从父类继承的方法,要求是公共的
Method[] methods = cls.getMethods();
System.out.println(Arrays.toString(methods));
//所有权限,但是只能获取本类中有的
methods = cls.getDeclaredMethods();
System.out.println(Arrays.toString(methods));
//获取指定的一个方法
Method method = cls.getDeclaredMethod("getName");
//创建一个对象
Goods good = new Goods(104,"手机");
//操作
System.out.println(method.invoke(good));
//静态方法 可以跟随对象调用,可以对象位置设置为null
method = cls.getDeclaredMethod("test",int.class,String.class);
//忽略权限
/*method.setAccessible(true);
System.out.println(method.invoke(null));;
System.out.println(method.invoke(good));;*/
//Type[] getGenericParameterTypes()
Type[] arr = method.getGenericParameterTypes();
//System.out.println(arr);
System.out.println(Arrays.toString(arr));
for(Type t:arr){
System.out.println(t.getTypeName());
}
}
}
二、XML
⑤DOM4J 解析xml
1. 获取流 SAXReader reader = new SAXReader();
2. 指定文件,加载文件,把xml文件加载到内存 Document
3. 操作标签内容
public class XMLDemo01 {
public static void main(String[] args) throws DocumentException {
//1.获取流
SAXReader reader = new SAXReader();
//2.加载xml文件
Document document = reader.read("src/goods.xml");
//3.解析数据
//跟标签
Element root = document.getRootElement();
System.out.println("根节点"+root.getName());
//子标签
List<Element> list = root.elements();
for(Element ele:list){
System.out.println(ele.getName());
System.out.println(ele.attributeValue("id"));
List<Element> ls = ele.elements();
for(Element e:ls){
System.out.println(e.getName()+"--->"+e.getData());
}
}
}
}
②获取xml文件中的内容,遍历内容,写出到xml文件
public class XMLDemo02 {
public static void main(String[] args) throws DocumentException, IOException {
//1.获取document
Document document = getDocument("src/goods.xml");
//2.遍历
print(document);
//3.写出
writeToXML(create());
print( getDocument("src/haha.xml"));
}
//创建Document
public static Document create(){
//1.创建一个Document对象
Document document = DocumentHelper.createDocument();
//2.添加根节点
Element root = document.addElement("Persons");
//3.添加子标签
Element ele = root.addElement("Person");
ele.addElement("name").addText("zhangsan");
ele.addElement("age").addText("18");
ele.addAttribute("id","1001");
Element ele2 = root.addElement("Person");
ele2.addElement("name").addText("lisi");
ele2.addElement("age").addText("19");
return document;
}
//写出到xml文件
public static void writeToXML(Document document) throws IOException {
//2.指定输出的标签格式
//OutputFormat format = OutputFormat.createCompactFormat(); //普通格式
OutputFormat format = OutputFormat.createPrettyPrint(); //美丽格式
//1.构建输出流 XMLWriter
XMLWriter wt = new XMLWriter(new FileWriter("src/haha.xml"),format);
//3.写出
wt.write(document);
//4.刷出
wt.flush();
//5.关闭
wt.close();
}
//封装遍历方法
public static void print(Document document){
//1.获取根节点
Element root = document.getRootElement();
System.out.println("根节点:"+root.getName());
//2.获取子节点
//List<Element> list = root.elements("good");
List<Element> list = root.elements();
for(Element ele:list){
System.out.println("子标签:"+ele.getName());
//获取遍历所有ele子元素的迭代器
Iterator<Element> it = ele.elementIterator();
while(it.hasNext()){
Element e = it.next();
System.out.println("孙子标签:"+e.getName()+"-->"+e.getText());
}
}
}
//获取Doucment对象
public static Document getDocument(String path) throws DocumentException {
//1.创建一个SaxReader
SAXReader reader = new SAXReader();
//2.加载xml文件
Document doc = reader.read(path);
//3.返回
return doc;
}
}