zoukankan      html  css  js  c++  java
  • 2019-06-06 Java学习日记 day27 反射

    类的加载概述和加载时机

    类的加载

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

      *加载

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

      *连接

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

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

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

      *初始化 

    加载时机

      *创建类的实例

      *访问类的静态变量,或者为静态变量赋值

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

      *初始化某个类的子类

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

    类加载器和分类

     类加载器

      *负责将.class文件加载到内存中,并为之生成对应的class对象。虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行

     类加载器的分类

      *Bootstrap ClassLoader 根类加载器

      *Extension ClassLoader 扩展类加载器

      *System ClassLoader 系统类加载器

     类加载器的作用

      *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类型的对象

    三种方式

      *object类的getClass()方法没判断两个对象是否是同一个字节码文件

      *静态属性class,锁对象

      *Clas类中静态方法forNamme(),读取配置文件

    import tan.jung.bean.Person;
    
    public class demo1_Reflcet {
    
        public static void main(String[] args) throws ClassNotFoundException {
            Class clazz1=Class.forName("tan.jung.bean.Person");
            
            Class clazz2 =Person.class;
            Person p =new Person();
            
            Class clazz3=p.getClass();
            
            System.out.println(clazz1 == clazz2);
            System.out.println(clazz2 == clazz3);
        }
    
    }
    案例

     

    forName配置

    import java.io.BufferedReader;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    
    public class demo2_Reflect {
    
        public static void main(String[] args) throws Exception {
            //没有反射
            //Juice j1=new Juice();  //购买榨汁机
            //j1.run(new Apple());    //向榨汁机放入苹果
            
            //j1.run(new Orange());  //Fruit f =new Orange
            
            
            //反射和配置
            BufferedReader br1=new BufferedReader(new FileReader("cofing.prt"));
            Class clazz=Class.forName(br1.readLine());
            Fruit f=(Fruit) clazz.newInstance();   //父类引用指向子类对象,水果引用指向了苹果对象
            Juice j=new Juice();
            j.run(f);
            
        }
    
    }
    interface Fruit{
        public void squeeze();
    }
    
    class Apple implements Fruit{
        public void squeeze(){
            System.out.println("榨出一杯苹果汁");
        }
    }
    class Orange implements Fruit{
        public void squeeze(){
            System.out.println("榨出一杯橙子汁");
        }
    }
    class Juice{
    //     public void run(Apple a){
    //         a.squeeze();
    //     }
    //     
    //     public void run(Orange o){
    //         o.squeeze();
    //     }
         public void run(Fruit f){
         f.squeeze();
    }
    }
    案例

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

      *Constructor

        *Class类的newInstance()方法是使用该类无参的构造函数创建对象,如果一个类没有无参的构造函数,就不能这样创建了,可以调用Class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance(“张三”,20)方法创建对象

    import java.lang.reflect.Constructor;
    
    import tan.jung.bean.Person;
    
    public class demo3_Constructor {
    
        public static void main(String[] args) throws Exception {
            Class clazz =Class.forName("tan.jung.bean.Person");
            //Person p =(Person) clazz.newInstance();  //通过无参创建对象
            Constructor c =clazz.getConstructor(String.class,int.class);//获取有参构造
            Person p=(Person) c.newInstance("张三",23);  //通过有参构造创建对象
            System.out.println(p);
        }
    
    }
    案例

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

      *Field

        *Class.getField(String)方法介意获取类中的指定字段(可见的),如果是私有的可以用getDeclaedField(“name”)放啊获取,通过set(obj,“李四”)方法可以设置指定对象上该字段的值,如果是私有的需要先调用setAccessible(true)设置访问权限,用获取的指定的字段套用get(obj)可以获取指定对象中该字段的值

    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    
    import tan.jung.bean.Person;
    
    public class demo4_Fiexd {
    
        public static void main(String[] args) throws Exception {
            Class clazz =Class.forName("tan.jung.bean.Person");
            Constructor c =clazz.getConstructor(String.class,int.class);//获取有参构造
            Person p=(Person) c.newInstance("张三",23);  //通过有参构造创建对象
            Field f =clazz.getDeclaredField("name");
            f.setAccessible(true);//去除私有权限
            f.set(p, "李四");
            System.out.println(p);
        }
    
    }
    案例

    通过反射获取方法并使用

      *Method

        *Class.getMethod(String,Class...)和Class.getDeclaredMethod(String,Class....)方法可以获取类中的指定方法,调用invoke(object,object...)可以调用该方法,Class.getMethod(“eat”)invoke(obj)Class.getMethod(“eat”.int.class)invoke(obj,10)

    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;
    
    import tan.jung.bean.Person;
    
    public class demo5_method {
    
        public static void main(String[] args) throws Exception {
            Class clazz =Class.forName("tan.jung.bean.Person");
            Constructor c =clazz.getConstructor(String.class,int.class);
            Person p=(Person) c.newInstance("张三",23);
            Method m =clazz.getMethod("eat");  //获取eat方法
            m.invoke(p);
            
            Method m2=clazz.getMethod("eat", int.class);    //获取有参的eat方法
            m2.invoke(p, 10);
        }
    
    }
    案例

    动态代理的概述和实现

    概述

      代理:本来应该自己做的事情,请人被人来做,被请的人就是代理对象

      动态代理:在程序运行过程中产生的这个对象,而程序运行过程中产生的对象其实就是我们刚才反射讲解的内容,过意,动态代理其实就是通过反射来生成一个代理

      在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理,我们有更强大的代理 cglib,Proxy类中的方法创建动态代理类对象

      public static object newProxyInstance(ClassLoader) loader,Class< ? > [ ] interfaces,InvocationHandler h )

      最终会调用InvocationHandler的方法

      InvocationHandler object invoke(object proxy ,Method method,object[ ] args)

    import java.lang.reflect.Proxy;
    
    public class Test {
    
        public static void main(String[] args) {
            /*userImp ui=new userImp();
            ui.add();
            ui.delete();
            System.out.println("------------");*/
            /*My m =new My(ui);
            user u=(user)Proxy.newProxyInstance(ui.getClass().getClassLoader(), ui.getClass().getInterfaces(), m);
            u.add();
            u.delete();*/
            
            StudentImp si=new StudentImp();
            si.login();
            si.submit();
            
            System.out.println("------------");
            My m =new My(si);
            Student u=(Student)Proxy.newProxyInstance(si.getClass().getClassLoader(), si.getClass().getInterfaces(), m);
            u.login();
            u.submit();
        }
    
    }
    
    
    //第二个包
    public interface Student {
        public void login();
        
        public void submit();
    }
    
    //第三个包
    public class StudentImp implements Student {
    
        @Override
        public void login() {
            System.out.println("登录");
    
        }
    
        @Override
        public void submit() {
            System.out.println("提交");
    
        }
    
    }

    设计模式

    概述

      模板方法木事就是定义一个算法的骨架,而将具体的算法延迟刀子类中来实现

    优点和缺点

      优点:使用模板方法木事,在定义算法骨架的同时,可以很灵活的实现具体的算法,猫族用户灵活多变的需求

      缺点:如果算法骨架有修改的话,则需要修改抽象类

    装饰

    单例

    简单工厂

    工厂方法

    适配器

    模板

    JDK5的新特性

    枚举概述

      是指将变量的值——列出来,变量的值只限于列出来的值的范围内。

    回想单列设计模式:单例类是一个类直邮一个实例

      那么多列类就是一个类有多个实例,但不是无限个数的实例,而是有限个数的实例。这才能是枚举类

     自动拆装箱

    泛型

    可变参数

    静态导入

    增强for循环

    互拆锁

    枚举

    枚举的注意事项

      定义枚举类要用关键字enum

      所有枚举类都是Enum的子类

      枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是尅省略的,但是如果枚举类其他的东西,这个分号就不能省略。建议不要省略

      枚举类可以有构造器,单必须是private的,它默认的也是private的

      枚举类也可以有抽象方法,但是枚举类必须重写该方法

      枚举类在

      switch语句中的使用

    枚举的常见方法

      int ordinal()

      int compareTo(E o)

      String name()

      String toString(

      <T> T valueOf (Class <T> type,String name)

      values()

      此方法虽然在JDK文档中查找不到,但每个枚举类都具有该方法,它遍历枚举类的所有枚举值非常方便

    JKD7新特性

      二进制字面量0b001

      数字字面量可以出现下划线

      switch 语句可以用字符串

      泛型简化,菱形泛型

      异常的多个catch合并,每个异常用或 |

      try-with-resources 语句

    JDK8新特性

      接口中可以定义有方法体的方法,如果是非静态,必须用default修饰

      如果是静态的就不用了 

  • 相关阅读:
    音频处理入门笔记
    python对象-多态
    python对象的不同参数集合
    python多重继承的钻石问题
    python对象的多重继承
    python类继承的重写和super
    Python继承扩展内置类
    python对象继承
    Python模块与包
    Pyhton对象解释
  • 原文地址:https://www.cnblogs.com/JungTan0113/p/10992350.html
Copyright © 2011-2022 走看看