zoukankan      html  css  js  c++  java
  • 多线程 Upload、类加载器、反射、配置文件

    summarize

    反射可以理解为是解剖,把文件所有的内容地毯式的查看,通过暴力反射将私有的内容进行呈现,想解剖一个类,就得获取此类字节码文件对象,同时可以通过反射进行对象的创建。要知晓类的加载形成.class文件最先执行(在类进内存的时候),然后再执行静态内容。通过反射获取成员变量、方法或构造方法都有四种方法,可利用泛型擦除和反射在集合中添加任意类型的元素,也可以利用反射配置文件,运行指定类的指定方法

    多线程针对于服务端(只修改服务端就可以让N个客户端对服务端进行上传)

    package com.oracle.demo05;
    //文件上传多线程,服务端
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    //让它实现Runnable
    public class Upload implements Runnable{
        private Socket socket=null;
    //    创建一个空参构造
        public Upload(){}
    //    创建一个有参构造
        public Upload(Socket socket){
            this.socket=socket;
        }
        public void run() {
            FileOutputStream fos=null;
            try{
    //        3.明确目的地
            File file=new File("f:\java\nihao");
    //        加个判定 如果该目录不存在,则创建
            if(!file.exists()){
                file.mkdirs();
            }
    //        给文件加上条件,让它不会重复 
            String filename="oracle"+System.currentTimeMillis()+".txt";
    //        明确目的地
            fos=new FileOutputStream(file+File.separator+filename);
    //        明确数据源
            InputStream in=socket.getInputStream();
    //        开始复制
            int len=0;
            byte[] bytes=new byte[1024];
            while((len=in.read())!=-1){
                fos.write(bytes, 0, len);
            }
    //        回复客户端
    //        获取字节输出流,回复客户端
            OutputStream out=socket.getOutputStream();
            out.write("上传很成功".getBytes());
        }catch(IOException ex){
            ex.printStackTrace();
        }finally{
    //        释放资源    
            try{
                fos.close();
            }catch(IOException e){
                e.printStackTrace();
                }
            }        
        }        
    }

     类加载器

    类的加载: 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。

    加载:就是指将class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象

    连接:验证 :是否有正确的内部结构,并和其他类协调一致

    准备 :负责为类的静态成员分配内存,并设置默认初始化值

    解析 :将类的二进制数据中的符号引用替换为直接引用

    初始化:以前讲过的初始化步骤

    类初始化时机:(进内存)

    ①. 创建类的实例

    ②. 类的静态变量,或者为静态变量赋值

    ③. 类的静态方法

    ④. 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象

    ⑤. 初始化某个类的子类

    ⑥. 直接使用java.exe命令来运行某个主类

    类加载器

    负责将.class文件加载到内存中,并生成对应的Class对象。

    类加载器的组成

    ①、Bootstrap ClassLoader 根类加载器:也称为引导类加载器,负责Java核心类的加载  比如System,String等。在JDK中JRE的lib目录下rt.jar文件中

    ②、Extension ClassLoader 扩展类加载器:负责JRE的扩展目录中jar包的加载 在JDK中JRE的lib目录下ext目录

    ③、 System ClassLoader 系统类加载器 :负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径

    反射

    反射:  JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

    Class类:  Class没有公共构造方法。Class对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。

     获取字节码的三种方式

    ①、通过object类中的getobject()方法

    ②、通过 类名.class获取到字节码文件对象(任意数据类型都具备一个class静态属性)

    ③、通过Class类中的方法(将类名作为字符串传递给Class类中的静态方法forName即可)

    package com.oracle.demo01;
    
    public class Person {
        private String name;
        public int age;
        public Person(){
            System.out.println("public Person()");
        }
        public Person(String name){
            this.name=name;
            System.out.println("public Person(String name)");
        }
        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + "]";
        }
        private Person(int age){
            this.age=age;
            System.out.println("private Person(int age)");
        }
        static{
            System.out.println("静态代码块");
        }
        public void sleep(String name,int age){
            System.out.println(name+"..."+age);
            System.out.println("public void sleep()");
        }
    //    公有空参
        public void eat(){
            System.out.println("public void eat()");
        }
    //    公有有参
        public void sleep(String name){
            System.out.println("public void sleep(String name)");
        }
    //    私有有参
        private void smoke(int age){
            System.out.println("private void smoke(int age)");
        }
    }
    ---------------------------------------------------
    package com.oracle.demo01;
    //获取类名三种方式
    public class Demo01 {
        public static void main(String[] args) throws ClassNotFoundException {
    //        获取字节码文件对象
    //        1.通过对象获取
            Class c1=new Person().getClass();
            System.out.println(c1);
    //        2.通过类名获取
            Class c2=Person.class;
            System.out.println(c2);
            System.out.println(c1==c2);//双 =  比的是地址
    //        3.通过Class类的静态方法获取
            Class c3=Class.forName("com.oracle.demo01.Person");//forname在JDBC出现过
        }
    }

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

    构造方法使用类Constructor表示。可通过Class类中提供的方法获取构造方法:

    1、返回一个构造方法

     public Constructor<T> getConstructor(Class<?>... parameterTypes) 获取public修饰, 指定参数类型所对应的构造方法

       public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 获取指定参数类型所对应的构造方法(包含私有的)

    2、 返回多个构造方法

     public Constructor<?>[] getConstructors() 获取所有的public 修饰的构造方法

     public Constructor<?>[] getDeclaredConstructors() 获取所有的构造方法(包含私有的)

    package com.oracle.demo02;
    //通过反射获取构造方法并使用
    import java.lang.reflect.Constructor;
    import java.lang.reflect.InvocationTargetException;
    
    import com.oracle.demo01.Person;
    
    public class Demo01 {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            method02();
    
        }
        public static void method01() throws ClassNotFoundException{
    //        获取字节码文件对象
            Class c=Class.forName("com.oracle.demo01.Person");
    //        获取所有公共构造方法数组
            //Constructor[] cons=c.getConstructors();
    //        System.out.println(cons);//重写toString方法得到地址
    //        获取所有构造方法
            Constructor[] cons=c.getDeclaredConstructors();
            for(Constructor con:cons){
                System.out.println(con);
            }        
        }
        public static void method02() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
    //        获取字节码文件对象
            Class c=Class.forName("com.oracle.demo01.Person");    
    //        获取空参构造方法对象
            Constructor con=c.getConstructor();
    //        调用构造方法创建对象
            Object obj=con.newInstance();
    //        向下转型
            Person p=(Person)obj;
            p.eat();
        }
        public static void method03() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
    //        获取字节码文件对象
            Class c=Class.forName("com.oracle.demo01.Person");    
    //        获取有参构造方法对象
            Constructor con=c.getConstructor(String.class);
    //        调用构造方法创建对象
            Object obj=con.newInstance("张三");
    //        向下转型
            Person p=(Person)obj;
            p.eat();        
        }

    通过反射,获取构造方法,创建对象

    通过构造方法类Constructor中的方法,创建对象

    public T newInstance(Object... initargs)

    //    获得私有构造 
    //    暴力反射:相当于抢银行 违反我们面向对象的封装思想,破坏了程序的安全性。(不推荐使用)
        public static void method04() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
    //        获取字节码文件对象
            Class c=Class.forName("com.oracle.demo01.Person");    
    //        获取有参构造方法对象
            Constructor con=c.getConstructor(int.class);
    //        暴力反射:取消java语言,检测访问
            con.setAccessible(true);
    //        调用构造方法创建对象
            Object obj=con.newInstance("18");
    //        向下转型
            Person p=(Person)obj;
            p.eat();        
        }
    }

    通过反射获取成员变量并使用

    在反射机制中,把类中的成员变量使用类Field(成员变量类)表示。可通过Class类中提供的方法获取成员变量:

    1、 返回一个成员变量

     public Field getField(String name) 获取指定的 public修饰的变量

     public Field getDeclaredField(String name) 获取指定的任意变量

    2、  返回多个成员变量

    public Field[] getFields() 获取所有public 修饰的变量

     public Field[] getDeclaredFields() 获取所有的 变量 (包含私有)

    package com.oracle.demo02;
    
    import java.lang.reflect.Field;
    
    public class Demo02 {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException {
            method02();
        }
    
        public static void method01() throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException {
            // 获取字节码文件对象
            Class c = Class.forName("com.oracle.demo01.Person");
            // 获取公共的成员变量
            Field f = c.getField("age");
    //        System.out.println(f);
            //快速创建对象----只能是空参的!
            Object obj=c.newInstance();
            //给对象的成员变量赋值
            f.set(obj, 18);
            
            System.out.println(obj);
        }
        public static void method02() throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException {
            // 获取字节码文件对象
            Class c = Class.forName("com.oracle.demo01.Person");
            // 获取私有的成员变量
            Field f = c.getDeclaredField("name");
    //        System.out.println(f);
            //暴力反射
            f.setAccessible(true);
            //快速创建对象----只能是空参的!
            Object obj=c.newInstance();
            //给对象的成员变量赋值
            f.set(obj, "张三");
            
            System.out.println(obj);
        }
    }

    通过反射获取成员方法并使用

    在反射机制中,把类中的成员方法使用类Method表示。可通过Class类中提供的方法获取成员方法:

    1、返回获取一个方法:

     public Method getMethod(String name, Class<?>... parameterTypes)

                            获取public 修饰的方法

      public Method getDeclaredMethod(String name, Class<?>... parameterTypes)

                            获取任意的方法,包含私有的

      参数1: name 要查找的方法名称; 参数2: parameterTypes 该方法的参数类型

    2、  返回获取多个方法:

      public Method[] getMethods() 获取本类与父类中所有public 修饰的方法

    public Method[] getDeclaredMethods() 获取本类中所有的方法(包含私有的)

     public Object invoke(Object obj,  Object... args)

    执行指定对象obj中,当前Method对象所代表的方法,方法要传入的参数通过args指定。

    泛型擦除

     泛型擦除:(注释和泛型不进class文件)  程序编译后产生的.class文件中是没有泛型约束的,这种现象我们称为泛型的擦除。那么,我们可以通过反射技术,来完成向有泛型约束的集合中,添加任意类型的元素

    package com.oracle.demo03;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    //泛型擦除
    import java.util.ArrayList;
    public class Demo01 {
        public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    //        泛型擦除
            ArrayList<String> arr=new ArrayList<String>();
    //        arr.add(123);//不能进calss文件:1注释2泛型
    //        反射
            Class c=arr.getClass();//获得字节码文件对象
            Method method=c.getMethod("add",Object.class);
    //        调用
            method.invoke(arr, 123);
            System.out.println(arr);
        }
    }

    反射配置文件

    通过反射配置文件,运行配置文件中指定类的对应方法

    读取Properties.txt文件中的数据,通过反射技术,来完成Person对象的创建

    package com.oracle.demo04;
    //反射配置文件
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.Properties;
    
    public class Demo {
        public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
    //        准备Properties集合存储键值对
            Properties pro=new Properties();
    //        明确数据源
            FileReader fr=new FileReader("src/pro.properties");
    //        将Properties文件中的键值对读取到Properties集合中
            pro.load(fr);
    //        从properties结合中读取完整的包名+类名
            String className=pro.getProperty("className");
    //        从properties结合中读取方法名
            String methodName=pro.getProperty("methodName");
    //        获取字节码文件对象 
            Class c=Class.forName(className);
    //        快速创建对象 
            Object obj=c.newInstance();
    //        获取成员方法对象
            Method method=c.getMethod(methodName);
    //        调用方法
            method.invoke(obj);
    //        释放资源
            fr.close();
        }
    }
  • 相关阅读:
    Websocket基础知识简记
    jmeter websocket接口测试
    软件测试的艺术 笔记(上)
    错误提示Unable to preventDefault inside passive event listener解决方法
    vue-cil3关闭eslint语法检查
    mongoDB无法启动服务器
    Vue之todoList
    react踩坑第一章
    父组件向孙子组件传值(Context)特性
    变量声明
  • 原文地址:https://www.cnblogs.com/zs0322/p/11081775.html
Copyright © 2011-2022 走看看