Java XML和反射详解

什么是 XML?

XML 指可扩展标记语言(EXtensible Markup Language)。 XML 是一种很像HTML的标记语言。
XML的设计宗旨是传输数据,而不是显示数据。
XML 标签没有被预定义。您需要自行定义标签。
XML 被设计为具有自我描述性。 XML 是 W3C的推荐标准。

XML 和 HTML 之间的差异

XML 不是 HTML 的替代。。

XML 和 HTML 为不同的目的而设计:

XML 被设计用来传输和存储数据,其焦点是数据的内容。
HTML 被设计用来显示数据,其焦点是数据的外观。
HTML 旨在显示信息,而 XML 旨在传输信息。

一、什么是反射:

1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。

(2)Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

二、反射的原理

下图是类的正常加载过程、反射原理与class对象:

Class对象的由来是将class文件读入内存,并为之创建一个Class对象。

在这里插入图片描述

三、反射的优缺点:

1、优点:在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。

2、缺点:(1)反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;

(2)反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。

四、反射的用途:

1、反编译:.class–>.java

2、通过反射机制访问java对象的属性,方法,构造方法等

3、当我们在使用IDE,比如Ecplise时,当我们输入一个对象或者类,并想调用他的属性和方法是,一按点号,编译器就会自动列出他的属性或者方法,这里就是用到反射。

4、反射最重要的用途就是开发各种通用框架。比如很多框架(Spring)都是配置化的(比如通过XML文件配置Bean),为了保证框架的通用性,他们可能需要根据配置文件加载不同的类或者对象,调用不同的方法,这个时候就必须使用到反射了,运行时动态加载需要的加载的对象。

五、反射机制常用的类:

Java.lang.Class;

Java.lang.reflect.Constructor;

Java.lang.reflect.Field;

Java.lang.reflect.Method;

Java.lang.reflect.Modifier;

1、获得Class:主要有三种方法:

(1)Object–>getClass

(2)任何数据类型(包括基本的数据类型)都有一个“静态”的class属性

(3)通过class类的静态方法:forName(String className)(最常用)

  @Test
    //获取Class --范围:所有的字节码文件
    public void test1() throws ClassNotFoundException {
        //方式一,通过类名
        Class c = Dog.class;   //Dog.java 编译后的字节码
        Class c1 = Book.class;   //Book.java编译后的字节码文件
//        方式二--通过对象
        Class c3 = new Dog().getClass();
//        方式三--通过类路径
        Class c4 = Class.forName("demo.Book");
        System.out.println(c4);
        System.out.println(c3);
    }

2.创建实例:通过反射来生成对象主要有两种方法:

(1)使用Class对象的newInstance()方法来创建Class对象对应类的实例。

   //1.管理无参构造
    @Test
    public void test2() throws Exception {
        //1.获取到某个类的字节码文件对象,即class的对象
        Class<Dog> c = Dog.class;
//        2.帮你调用无参构造
        Dog dog = c.newInstance();
        System.out.println(dog);
    }

(2)先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建对象,这种方法可以用指定的构造器构造类的实例。

    //2.管理有参构造
    @Test
    public void test3() throws Exception {
//        1.获取到某个类的字节码文件对象,即class的对象
        Class<Dog> c = Dog.class;
//        2.获取有参构造的管理对象--2个参数的那个
        Constructor<Dog> con = c.getDeclaredConstructor(String.class);
//        3.帮助Dog类调用有参构造
        Dog dog = con.newInstance("旺财");
        System.out.println(dog);
    }

3、通过反射获取构造方法并使用:

(1)批量获取的方法:
public Constructor[] getConstructors():所有"公有的"构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)

(2)单个获取的方法,并调用:
public Constructor getConstructor(Class… parameterTypes):获取单个的"公有的"构造方法:
public Constructor getDeclaredConstructor(Class… parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;

(3) 调用构造方法:

Constructor–>newInstance(Object… initargs)

newInstance是 Constructor类的方法(管理构造函数的类)

    //3.管理属性
    @Test
    public void test4() throws Exception {
        //1.获取到某个类的字节码文件对象,即Class的对象
        Class<Dog> c = Dog.class;
        //2.获取某个属性的管理对象
        Field f = c.getDeclaredField("name");
        //先创建一个狗狗对象
        Dog dog = c.newInstance();
        f.setAccessible(true); //开启私有属性操作权限
        //3.帮助dog给name属性赋值
        f.set(dog, "来福");
        System.out.println(dog);
    }
        //4.管理方法
    @Test
    public void test5() throws Exception {
        //1.获取到某个类的字节码文件对象,即Class的对象
        Class<Dog> c = Dog.class;
        //2.获取某个方法setAge(int age)的管理对象
        Method m = c.getDeclaredMethod("setAge", int.class);
        //先创建一个狗狗对象
        Dog dog = c.newInstance();
        //3.帮助dog给调用setAge方法
        m.invoke(dog, 3);
        System.out.println(dog);
        //管理toString方法
        Method m2 = c.getDeclaredMethod("toString");
        System.out.println(m2.invoke(dog));
    }

六、反射结合泛型案例

将一个map中的数据转存到一个实体类对象中。

 @Test//案例一:将一个map中的数据转存到一个实体类对象中。
    public void test5() throws Exception {
        HashMap<String, Object> map = new HashMap<>();
        map.put("name","旺财");
        map.put("age",3);
        Dog dog = getObject(map, Dog.class);
        System.out.println(dog);

    }
    public <T>T getObject(Map<String,Object> map, Class<T> c) throws Exception {
        T t = c.newInstance();
        //1.拆开map
        Set<Map.Entry<String, Object>> entries = map.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            String key = entry.getKey();
            //2.将map中的值存入T这个类的对象属性中
            Field f = c.getDeclaredField(key);
            f.setAccessible(true);
            f.set(t,entry.getValue());
        }
        return t;
    }

七、xml和反射综合案例

宠物管理系统

1.预先定义好父类:动物类,子类:狗狗类,企鹅类,大象类,
2.在xml文件中配置各个宠物类的全路径名
3.编写一个宠物领养方法,根据用户输入的宠物名称,从xml读取相应的类路径,使用反射构建宠物对象,并返回。

注意:使用父类作为方法返回值,字符串作为参数。

<?xml version="1.0" encoding="UTF-8" ?>
<animal>
    <狗狗>
        <name>旺财</name>
        <class>reflect.pet.Dog</class>
    </狗狗>
    <企鹅>
        <name>皮皮</name>
        <class>reflect.pet.Penguin</class>
    </企鹅>
    <大象>
        <name>肉肉</name>
        <class>reflect.pet.Elephant</class>
    </大象>
</animal>

 @Test
    public void test1() throws Exception {
        Scanner sc=new Scanner(System.in);
        System.out.println("请选择您要领养的宠物:狗狗,企鹅,大象");
        String name = sc.next();
        Animal animal = getAnimal(name);
        System.out.println(animal);
    }

    public Animal getAnimal(String name) throws Exception {
        // 1.创建解析器
        SAXReader reader = new SAXReader();
			// 解析xml文档,得到document对象
        Document document = reader.read("src/reflect1/pet/pet.xml");
			// 根据document对象获取根节点
        Element root = document.getRootElement();
			// 查找根节点下的子节点 element() elements()
        Element animal = root.element(name);
        String className = animal.element("class").getText();
        //2.使用反射创建对象
        return (Animal) Class.forName(className).newInstance();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值