博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2019-06-06 Java学习日记 day27 反射
阅读量:4682 次
发布时间:2019-06-09

本文共 7170 字,大约阅读时间需要 23 分钟。

类的加载概述和加载时机

类的加载

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

  *加载

    *就是指将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修饰

  如果是静态的就不用了 

 

转载于:https://www.cnblogs.com/JungTan0113/p/10992350.html

你可能感兴趣的文章
linux 里 /etc/passwd 、/etc/shadow和/etc/group 文件内容解释
查看>>
一.并发编程 (进程操作系统简介)
查看>>
深入理解vsto,开发word插件的利器
查看>>
PHP 在5.1.* 和5.2.*之间 PDO数据库操作中的不同!
查看>>
Laravel学习笔记之乱七八糟
查看>>
导入properties时的坑
查看>>
java校验maven下载的jar文件
查看>>
python——网络编程
查看>>
C++练习01 ---- 打印杨辉三角
查看>>
关于ajax中执行 window.location.href不跳转问题
查看>>
冲鸭队(第二周)
查看>>
【Luogu】P1144最短路计数(BFS)
查看>>
android 的闪屏效果
查看>>
Python还是很重要的,不能丢。学习IF和WHILE
查看>>
浅谈C++多态性
查看>>
金牌架构师:我们是这样设计APP数据统计产品的
查看>>
导出python的环境
查看>>
多维数据库 Oracle Essbase 和 IBM Cogons 底层原理
查看>>
各种小结
查看>>
virtualbox--在win7设置ubuntu虚拟机网络
查看>>