Java高级语言笔记(3)

Java高级语言笔记(3)

2.5反射机制

Java反射机制:是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息类创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展。

  • 创建student类(以下代码的student类都是基于此)
package com.kg.test;

/**
 * @author ZRB
 * @description
 * @date 2023/8/28 14:57
 */
public class Student {
   private String no ;
   String name;
   protected String sex;
   public int age;
   public Student(){

   }
   private Student(String no){
       this.no = no;
   }

    public Student(String no, String name, String sex, int age) {
        this.no = no;
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public String getNo() {
        return no;
    }

    public void setNo(String no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    private void sayHi(){
        System.out.println(String.format("您好!我叫%s,今年%s岁,性别是%s,学号为%s",getName(),getAge(),getSex(),getNo()));
    }
    public void study(int time){
        System.out.println("我是"+this.getName()+",我每天学习"+time);
    }
}

  • 创建测试类Test01
package com.kg.test;

/**
 * @author ZRB
 * @description: 获取Class类的对象:我们要想通过反射去使用一个类,首先我们要获取到该类的字节码文件对象,也就是类型为Class类型  **			的对象
 * @date 2023/8/28 15:23
 */
public class Test04 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取类型的的class对象,就是该类型的字节码文件对象。通过该对象,可以在程序运行的过程中动态创建对象,动态操作对象的原因
        //获取字节码对象:方法一,通过类型、class属性获取
        Class<Student> stuclass1 = Student.class;
        System.out.println(stuclass1);
        //方法二:通过getClass()方法获取
        Class<? extends Student> stuclass2 = new Student().getClass();
        System.out.println(stuclass2);
        //方式三:通过Class.forName方法。指定类的完整名获取。注意:类的完整名是”包名、类名“
        Class<?> stuclass3 = Class.forName("com.kg.test.Student");
        System.out.println(stuclass3);
        /*
        注意:上面的代码跟下面的代码,一定要区分开,上面的代码返回的是stundent类型的字节码文件对象,下面的代码直接创建一个stundent类型对象
         */
        Student student = new Student();
        System.out.println(student);
        /*
        其实在我们创建一个studnet对象时,java虚拟机也是通过student类型的class对象,去创建student对象的
        反射机制,只是这种被动方式,改成主动的方式
         */
    }
}

2.5.1反射获取构造方法并使用

Class类中用于获取构造方法的方法

  • Constructor<?>[] getConstructors():返回所有公共构造方法对象的数组
  • Constructor<?>[] getDeclaredConstructors():返回所有构造方法对象的数组
  • Constructor getConstructor(Class<?>…parameterTypes):返回单个公共构造方法对象
  • Constructor getDeclaredConstructor(Class<?>…parameterTypes):返回单个构造方法对象

Constructor类中用于创建对象的方法

  • T newInstance(Object…initargs):根据指定的构造方法创建对象
  • public void setAccessible(boolean flag):值为true,取消访问检查
Class<?> c = Class.forName("test.Student");
// 获取公共的构造方法
// Constructor<?>[] cons = c.getConstructors();
// 获取所有构造方法
Constructor<?>[] cons = c.getDeclaredConstructors();
for(Constructor con : cons){
  System.out.println(con)
}
// 获取构造方法对象
Constructor<?> con = c.getConstructor();
// 创建对象实例
Object obj = con.newInstance();
System.out.println(obj);
// 获取Class对象
Class<?> c = Class.forName("test.Student");
// 基本数据类型也可以通过.class得到对应的Class类型
Constructor<?> con = c.getConstructor(String.class,int.class,String.class);
Object obj = con.newInstance("张三",20,"北京");
System.out.println(obj);
// 获取Class对象
Class<?> c = Class.forName("test.Student");
// 基本数据类型也可以通过.class得到对应的Class类型
Constructor<?> con = c.getConstructor(String.class);
// 暴力反射
con.setAccessible(true);
Object obj = con.newInstance("张三");
System.out.println(obj);

2.5.2返回获取成员变量并使用

Class类中用于获取成员变量的方法

  • Field[] getFields():返回所有公共成员变量对象的数组
  • Field[] getDeclaredFields():返回所有成员变量对象数组
  • Field getField(String name):返回单个公共成员变量对象
  • Field getDeclaredField(String name):返回单个成员变量对象

Field类中用于给成员变量赋值的方法

  • void set(Object obj,Object value):给obj对象的成员变量赋值为value
// 获取Class对象
Class<?> c = Class.forName("test.Student");
// 获取公共成员变量
// Field[] fields = c.getFields();
// 获取成员变量
Field[] fields = c.getDeclaredFields();
for(Field field : fields){
  System.out.println(field);
}

// Field addressField = c.getField("address");
Field addressField = c.getDeclaredField("address");

// 获取无参构造方法创建对象
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
// 给obj对象的成员变量addressField赋值北京
addressField.set(obj,"北京");
System.out.println(obj);

2.5.3 反射获取成员方法并使用

Class类中用于获取成员方法的方法

  • Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的
  • Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
  • Method getMethod(String name,Class<?>…parameterTypes):返回单个公共成员方法对象
  • Method getDeclaredMethod(String name,Class<?>…parameterTypes):返回单个成员方法对象

Method类中用于调用成员方法的方法

  • Object invoke(Object obj,Object…args):调用obj对象的成员方法,参数是args,返回值是Object类型
package com.kg.test;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author ZRB
 * @description:使用反射获取成员方法并使用
 * @date 2023/8/29 8:37
 */
public class Test07 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //获取Student类型的class对象
        Class<?> studentClass = Class.forName("com.kg.test.Student");
        //getMethods方法:获取所有的公共方法,包括自己的所有公共方法和继承的方法
        Method[] methods = studentClass.getMethods();
        System.out.println("公共方法:");
        for (Method m:methods) {
            System.out.println(m);
        }
        //getDeclaredMethods方法:获取所有的方法,只包含自己的所有方法
        Method[] declaredMethods = studentClass.getDeclaredMethods();
        System.out.println("所有方法:");
        for (Method method:declaredMethods){
            System.out.println(method);
        }
        System.out.println("-----------------------------------------");
        //获取单个公共方法(可以获取自己的也可以获取继承的)
        Method setNo = studentClass.getMethod("setNo", String.class);
        System.out.println(setNo);
        Method study = studentClass.getMethod("study", int.class);
        System.out.println(study);
        //获取单个方法(可以获取私有的也可以获取公共的,但是获取不到继承的)
        Method sayHi = studentClass.getDeclaredMethod("sayHi");
        System.out.println(sayHi);
        //执行获取到的方法
        System.out.println(" 1.得到构造函数对象");
        Constructor<?> constructor = studentClass.getConstructor();
        System.out.println("2.创建实例对象");
        Object o =constructor.newInstance();
        System.out.println("3.执行对象身上的指定方法");
        setNo.invoke(o,"张三");
        study.invoke(o,5);
        //注意:sayhi是私有方法
        sayHi.setAccessible(true);
        sayHi.invoke(o);
    }
}

2.5.4 使用反射向集合中添加字符串

package com.kg.test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

/**
 * @author ZRB
 * @description:向int集合中添加字符串
 * @date 2023/8/29 9:34
 */
public class Test01 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ArrayList<Integer> list = new ArrayList<Integer>();
        //使用反射技术,得到list对象类型的class对象
        Class<? extends ArrayList> aClass = list.getClass();
        //根据arraylist对象类型的class对象,反射得到它的add方法对象
        Method add = aClass.getMethod("add", Object.class);
        //执行list对象的add方法,添加成员
        list.add(100);//使用正常手法给集合对象添加成员
        list.add(200);
        add.invoke(list,"hello");//使用反射手法给对象添加成员
        add.invoke(list,"word");
        /*
        根据上面的代码,可以给发现使用反射技术能向int集合中添加字符串成员
        说明,泛型集合,只是jdk表层的一种封装,集合的底层类型依然是Object
         */
        System.out.println(list);

    }
}

2.6 XML( EXtensible Markup Language)

XML概述

  • XML的全称为(EXtensible Markup Language),是一种可扩展的标记语言
  • 标记语言:通过标签来描述数据的一门语言(标签有时我们也将其称为元素)
  • 可扩展:标签的名字是可以自己定义的
  • 语法规则一:
语法规则示例代码
是由一对尖括号和一组合法标识符组成
在xml标签往往是成对出现,有开始也有结束
在xml有一些特殊的标签也可以不成对出现,但是必须要存在结束标记
在xml中标签可以定义属性,但是属性必须通过引号引起来
标签可以进行正确嵌套 zhangsan
  • 语法规则二:
语法规则示例代码
xml文件的后缀名普遍都是xmluser.xml,students.xml
xml要有文档声明,文档声明必须是第一行第一列<?xml version="1.0" encoding="utf-8"?>
xml必须要存在一个根标签,并且有且仅有一个
xml文件中可以定义注释信息
xml文件中可以存在以下特殊字符&lt;&gt;
xml文件中可以存在CDATA区(写特殊字符)<![CDATA[a\
  • 创建student.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!--xml文件头部必须存在<?xml version="1.0" encoding="UTF-8" ?>-->
<students>
    <student no="1001">
        <name>张三</name>
        <age>22</age>
        <sex></sex>
        <score value="99"/>
    </student>
    <student no="1002">
        <name>李四</name>
        <age>26</age>
        <sex></sex>
        <score value="66"/>
    </student>
    <student no="1002">
        <name>王五</name>
        <age>18</age>
        <sex></sex>
        <score value="19"/>
    </student>
</students>
<!--
    xml是可扩展标记语言:表示标签和标签属性都是可自由扩展的,xml文件的作用是根据自定义格式保存数据
    <?xml version="1.0" encoding="UTF-8" ?>
    是xml文件声明,必须放置在第一行,文档声明中必须要定义version属性,表示版本,通常还会设置encodin="UTF-8",指定编码格式
     每个xml文件必须要有一个根节点,并且只有一个根节点,xml文件通过节点的文本和节点的属性保存数据
     xml中的节点必须要成对出现,单标签必须要自闭和,否则就报错
-->

2.6.1解析xml文件

  • 创建解析类Test(解析上面student.xml文件)
package com.kg.xml;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.time.format.SignStyle;
import java.util.List;

/**
 * @author ZRB
 * @description:解析xml文件
 * @date 2023/8/29 14:53
 */
public class Test {
    public static void main(String[] args) throws FileNotFoundException, DocumentException {
        //创建一个xml文件解析器
        SAXReader reader =new SAXReader();
        //获取document对象(可以理解为要解析的整个xml文件对象)
        Document document = reader.read(new FileInputStream("Chapter07\\src\\com\\kg\\xml\\student.xml"));
        //获取xml文档对象的根节点
        Element root =document.getRootElement();
        //获取指定节点名称的所有子节点
       List<Element> student = root.elements("student");
        System.out.println("学号\t\t姓名\t\t性别\t\t年龄\t\t成绩");
        for (Element element :student) {
            //获取当前节点的no属性的值
            String no = element.attribute("no").getValue();
            //获取当前节点的子节点的文本值
            String name = element.element("name").getText();
            String age = element.element("age").getText();
            String sex = element.element("sex").getText();
            //获取当前节点的score子节点的value属性值
            String score = element.element("score").attribute("value").getValue();
            System.out.println(no+"\t"+name+"\t\t"+sex+"\t\t"+age+"\t\t"+score);
        }
    }
}

2.6.2解析上面 student.xml 并把数据放在集合中

  • 创建student类
package com.kg.xml;

/**
 * @author ZRB
 * @description
 * @date 2023/8/29 15:53
 */
public class Student {
    private String no;
    private String name;
    private int age;
    private String sex;
    private double score;

    public Student() {
    }

    public Student(String no, String name, int age, String sex, double score) {
        this.no = no;
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.score = score;
    }

    public String getNo() {
        return no;
    }

    public void setNo(String no) {
        this.no = no;
    }

    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 String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "no='" + no + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                ", score=" + score +
                '}';
    }
}
  • 创建test类然后放入数据(原则:先解析再放入)
package com.kg.xml;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author ZRB
 * @description
 * @date 2023/8/29 15:56
 */
public class Test01 {
    public static void main(String[] args) throws FileNotFoundException, DocumentException {
        //创建一个学生集合
        List<Student> students = new ArrayList<Student>();
        //解析一个xml文件,并将数据添加到该集合中
        SAXReader reader = new SAXReader();
        Document document = reader.read(new FileInputStream("Chapter07\\src\\com\\kg\\xml\\student.xml"));
        //获取xml文档对象的根节点
        Element root =document.getRootElement();
        //获取指定节点名称的所有子节点
        List<Element> student = root.elements("student");
        for (Element  element :student) {
            Student student1 =new Student();
            //获取当前节点的no属性的值
            String no = element.attribute("no").getValue();
            //获取当前节点的子节点的文本值
            String name = element.element("name").getText();
            String age = element.element("age").getText();
            String sex = element.element("sex").getText();
            //获取当前节点的score子节点的value属性值
            String score = element.element("score").attribute("value").getValue();
            student1.setNo(no);
            student1.setName(name);
            student1.setAge(Integer.parseInt(age));
            student1.setSex(sex);
            student1.setScore(Double.parseDouble(score));
            students.add(student1);
        }
        //遍历集合
        for (Student s:students) {
            System.out.println(s);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值