JAVASE18

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 + '\'' +
                '}';
    }
}
③通过反射操作属性
  1. Class对象

  2. 获取某一个类型的属性
    字段 getField(String name) 返回 字段对象,该对象反映此 类对象表示的类或接口的指定公共成员字段。
    字段[] getFields()
    字段 getDeclaredField(String name) 返回 字段对象,该对象反映此 类对象表示的类或接口的指定声明字段。
    字段[] getDeclaredFields()

  3. 操作属性
    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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值