Java后端笔记16-反射

模拟服务器Tomcat

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Create by xiye on 2019/12/9 11:22
 */
public class MyTomcat {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(1314);

        while (true) {
            Socket socket = serverSocket.accept();
            new Thread(() -> {
                try {
                    // 获取请求
                    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    byte[] bytes = new byte[1024];
                    String readLine = br.readLine();
                    //System.out.println(readLine);
                    // 获取请求体第一行的地址
                    String path = readLine.split(" ")[1].substring(1);

                    //System.out.println(path.lastIndexOf("?"));

                    path = path.split("\\?")[0];    // 字体文件含有?,去除掉

                    System.out.println(getHost(socket) + "请求:" + path);

                    File file = new File(path);
                    if (file.exists()) {
                        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
                        OutputStream os = socket.getOutputStream();
                        // 写入HTTP协议响应头,固定写法
                        os.write("HTTP/1.1 200 OK\r\n".getBytes());
                        if (file.getName().endsWith(".css")) {
                            os.write("Content-Type:text/css\r\n".getBytes());
                        } else {
                            os.write("Content-Type:text/html\r\n".getBytes());
                        }
                        // 必须要写入空行,否则浏览器不解析
                        os.write("\r\n".getBytes());
                        // 文件内容
                        byte[] response = new byte[4 * 1024];
                        int len;
                        while ((len = bis.read(response))!= -1) {
                            os.write(response, 0, len);
                        }

                        os.close();
                        bis.close();
                    } else {
                        System.err.println("找不到" + file.getName());
                    }
                    br.close();
                    socket.close();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
    private static String getHost(Socket socket) {
        return socket.getInetAddress().getHostAddress() + ":" + socket.getPort();
    }
}

反射

反射是一种机制,利用该机制可以在程序运行过程中对类进行解剖并操作类中的方法,属性,构造方法等成员。
Java后端笔记16-反射_第1张图片
Java后端笔记16-反射_第2张图片
Java后端笔记16-反射_第3张图片
Java后端笔记16-反射_第4张图片

利用反射获取到属性、调用方法体的使用:

import com.xiye.bean.Student;

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

/**
 * Create by xiye on 2019/12/9 15:53
 */
public class Demo1_反射 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        // 方式一
        Class stu1 = Student.class;
        // 方式二
        Class stu2 = new Student().getClass();
        // 方式三
        Class stu3 = Class.forName("com.xiye.bean.Student");

        System.out.println("获取全路径名和类名:" + stu1.getName());
        System.out.println("只获取类名:" + stu2.getSimpleName());
        System.out.println("就是new一个对象,对应无参构造器:" + stu3.newInstance());

        //methodConstructors(stu3);
        methodMethod(stu3);

        //methodField(stu3);
    }

    private static void methodField(Class stu3) throws InstantiationException, IllegalAccessException, NoSuchFieldException {
        Object o1 = stu3.newInstance();
        // 获取public修饰、指定名称的属性
        System.out.println("\n=============获取public修饰、指定名称的属性===========");
        Field sex = stu3.getField("sex");
        sex.set(o1, "男");                      //   类似o1.sex = "男";
        System.out.println(sex.get(o1));		//	 获取属性值
        System.out.println(o1);

        // 获取所有权限、指定名称的属性
        System.out.println("\n=============获取所有权限、指定名称的属性===========");
        Field name = stu3.getDeclaredField("name");
        name.setAccessible(true);
        name.set(o1, "李峰");
        System.out.println(o1.toString());

        // 获取public修饰的所有属性
        System.out.println("\n=============获取public修饰的所有属性===========");
        Field[] f1 = stu3.getFields();
        for (Field f : f1) {
            System.out.println(f.getType().getSimpleName() + " " + f.getName());
        }

        // 获取所有属性
        System.out.println("\n=============获取所有属性===========");
        Field[] f2 = stu3.getDeclaredFields();
        for (Field f : f2) {
            System.out.println(f.getType().getSimpleName() + " " + f.getName());
        }
    }

    private static void methodMethod(Class stu3) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        // 获取public修饰的指定方法名和参数的方法
        System.out.println("\n=============获取public修饰的指定方法名和参数的方法===========");
        Method m1 = stu3.getMethod("getName");
        System.out.println(m1.toString());

        // 获取指定方法名和参数的方法
        System.out.println("\n=============获取指定方法名和参数的方法===========");
        Method m2= stu3.getDeclaredMethod("setName", String.class);

        Object o1 = stu3.newInstance();
        m2.invoke(o1, "李四");

        System.out.println(m2.toString());
        System.out.println(o1.toString());

        // 获取到方法体
        Method m0 = stu3.getDeclaredMethod("study");
        m0.setAccessible(true);     // 暴力访问私有方法
        m0.invoke(null);        // 设置为null访问静态的

        // 如果调用普通方法,invoke指定方法所属的对象,若有参数,添加参数即可(getMethod获取方法时也要指定参数的类型)
        Method m = stu3.getMethod("common", String.class);
        m.invoke(o1, "我是参数");       // 类似o1.common("我是参数");


        // 获取所有public修饰的方法(包含父类)
        System.out.println("\n=============获取所有public修饰的方法(包含父类)===========");
        Method[] m3= stu3.getMethods();
        for (Method method : m3) {
            System.out.println(method);
        }

        // 获取类中所有的方法(不包含包含父类)
        System.out.println("\n=============获取类中所有的方法(不包含包含父类)===========");
        Method[] m4= stu3.getDeclaredMethods();
        for (Method method : m4) {
            System.out.println(method);
        }
    }

    private static void methodConstructors(Class stu3) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        // 获取有参构造器
        System.out.println("\n=============获取有参构造器===========");
        Constructor c1 = stu3.getDeclaredConstructor(String.class, Integer.class);
        Object o1 = c1.newInstance("李四", 21);     // 类似new Student("李四", 21);
        System.out.println(o1.toString());

        // 获取私有的构造器
        System.out.println("\n=============获取私有的构造器===========");
        Constructor c2 = stu3.getDeclaredConstructor(String.class);
        c2.setAccessible(true);         // 暴力反射,破坏了封装性
        Object o2 = c2.newInstance("张三");
        System.out.println(o2.toString());


        // 获取所有构造器
        System.out.println("\n=============获取所有构造器===========");
        Constructor[] c3 = stu3.getDeclaredConstructors();
        for (Constructor c : c3) {
            System.out.println(c);
        }

        // 获取public修饰的指定构造器
        System.out.println("\n=============获取public修饰的指定构造器===========");
        Constructor c4 = stu3.getConstructor();
        Constructor c5 = stu3.getConstructor(String.class, Integer.class);
        System.out.println(c4.toString());
        System.out.println(c5.toString());

        // 获取public修饰的所有构造器
        System.out.println("\n=============获取public修饰的所有构造器===========");
        Constructor[] c6 = stu3.getConstructors();
        for (Constructor c : c6) {
            System.out.println(c);
        }
    }
}
package com.xiye.bean;

/**
 * Create by xiye on 2019/12/9 15:54
 */
public class Student {
    private String name;
    private Integer age;
    public String sex;

    public Student() {}

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    private static void study() {
        System.out.println("私有静态方法:学习使我快乐");
    }

    public void common(String str) {
        System.out.println("普通方法:" + str);
    }

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }
}

反射工厂模拟

import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
import java.util.Set;

/**
 * Create by xiye on 2019/12/9 18:00
 */
public class Demo2_示例 {
    public static void main(String[] args) throws Exception {
        Object obj = getObject();
        System.out.println(obj.toString());
    }

    private static Object getObject() throws Exception {

        Properties properties = new Properties();
        properties.load(new InputStreamReader(Demo2_示例.class.getResourceAsStream("/info.properties"), "GBK"));
        Set keys = properties.stringPropertyNames();

        String pkg = properties.getProperty("class");
        //
        Class aClass = Class.forName(pkg);

        Object obj = aClass.newInstance();
        for (String k : keys) {
            if (!"class".equals(k)) {
                String value = properties.getProperty(k);
                /*Field field = aClass.getDeclaredField(k);

                field.setAccessible(true);
                if (field.getType() == Integer.class) {
                    field.set(obj, Integer.parseInt(value));
                } else {
                    field.set(obj, value);
                }*/

                setField(aClass, obj, k, value);
            }
        }
        return obj;
    }

    /**
     * 利用封装方法进行属性赋值
     * @param aClass 反射类
     * @param obj    类对象
     * @param k      属性
     * @param value  属性值
     * @throws Exception
     */
    private static void setField(Class aClass, Object obj, String k, String value) throws Exception {
        // 处理封装方法的属性
        for (Method method : aClass.getMethods()) {
            if (method.getName().equals(getSetMethodName(k))) {
                if (method.equals(aClass.getMethod(getSetMethodName(k), method.getParameterTypes()[0]))) {
                    if (method.getParameterTypes()[0] == Integer.class) {
                        method.invoke(obj, Integer.parseInt(value));
                    } else {
                        method.invoke(obj, value);
                    }
                }
                break;
            }
        }
        // 处理没有封装方法并且是public的属性
        for (Field field : aClass.getFields()) {
            if (field.getName().equals(k)) {
                if (field.equals(aClass.getField(k))) {
                    field.set(obj, value);
                }
            }
        }
    }

    private static String getSetMethodName(String s) {
        /*if (s.length() == 1) {
            return s.toUpperCase();
        }*/
        return "set" + s.substring(0, 1).toUpperCase() + s.substring(1, s.length());
    }
}

你可能感兴趣的:(后端笔记)