day27

27.01 反射(类的加载概述和加载时机)
 1.类的加载
  当程序要使用某个类时,如果该类还未加载到内存中,系统会通知加载,连接,初始化三步来实现对这个类初始化
 a.加载
  是指将.class文件读入内存中,并创建一个class对象。任何类被使用时系统都会建立一个class对象
 b.连接
  验证:是否有正确的内部结构,并和其他类协调一致
  准备:负责为类的静态成员分配内存,并设置默认初始化值
  解析:将类的二进制数据中的符号引用替换为直接引用
   c.初始化
 2.加载时机
  创建类的实例
  访问类的静态变量,或者静态变量赋值
  调用类的静态方法
  使用反射方式来强制创建某个类或者接口对应的Java.lang.class对象
  初始化某个类的子类
  直接使用Java.exe命令来运行某个主类
27.02 反射(类加载器的概述和分类)
 1.类加载器的概述
  负责将.class 文件加载到内存中,并为之生成对应的class对象
 2.类加载器的分类
  Bootstrap ClassLoader 跟类加载器 负责Java核心类的加载
  Extension ClassLoader 扩展类加载器 负责JRE的扩展目录中jar包的加载
  system ClassLoader 系统类加载器
27.03 反射(反射概述)
 1.反射概述
  Java反射机制是在运行状态中,
  对于任何一个类,都可以知道这个类的所有属性和方法
  对于任何一个对象,都可以调用它的任意一个方法和属性
 2.三种方式
  a.object类的getclass()方法,判断两个对象是否是同一个字节码文件
  b.静态属性class,锁对象
  c.class类中静态方法forName(),读取配置文件
 3.案例

package day27;
import com.heima.bean.Person;
public class day27_03 {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
Class clazz1 = Class.forName("com.heima.bean.Person");
Class clazz2 = Person.class; Person p =new Person();
Class clazz3 = p.getClass(); System.out.println(clazz1 == clazz2); //判断字节码是否相同
System.out.println(clazz2 == clazz3);
}
}
-------------------------
package day27;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
public class day27_03_eg {
public static void main(String[] args) throws Exception{
//Juicer j =new Juicer(); //购买榨汁机
//j.run(new Apple()); //向榨汁机中放入苹果
//j.run(new Orange()); //向榨汁机中放入苹果 //j.run(new Orange()); //父类引用指向子类对象 //新建config.properties文件,并在里面输入包名.类名
BufferedReader br = new BufferedReader(new FileReader("config.properties"));
Class clazz = Class.forName(br.readLine());
Fruit f = (Fruit) clazz.newInstance();
Juicer j = new Juicer();
j.run(f);
}
} /*class Apple{
public void squeeze(){
System.out.println("榨出一杯苹果汁");
}
}*/
interface Fruit{ //创建接口Fruit
public void squeeze();
}
class Apple implements Fruit{ //继承接口Fruit并重写原接口的方法
public void squeeze(){
System.out.println("榨出一杯橘子汁");
}
}
class Juicer{
/*public void run(Apple a){
a.squeeze();
}
public void run(Orange o){
o.squeeze();
}*/
public void run(Fruit f){
f.squeeze();
}
}

27.04 反射(Class.forName()读取配置文件)
27.05 反射(通过反射获取带参构造方法)
 Constructor
  class类的newInstance()方法是使用该类无参的构造函数创建对象,如果一个类没有无参的构造函数,就不能这样创建的
  可以调用class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数,
  再调用Constructor类的newInstance("张三",20)方法创建

package day27;
import java.lang.reflect.Constructor;
import com.heima.bean.Person;
public class day27_05 {
/**
* Constructor
class类的newInstance()方法是使用该类无参的构造函数创建对象,如果一个类没有无参的构造函数,就不能这样创建的
可以调用class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数,
再调用Constructor类的newInstance("张三",20)方法创建
* @throws Exception
* @throws SecurityException
*/
public static void main(String[] args) throws SecurityException, Exception {
Class clazz = Class.forName("com.heima.bean.Person");
Constructor c = clazz.getConstructor(String.class,int.class);//为什么是这两个.class
//进入com.heima.bean.Person,其构造方法为:public Person(String name, int age),含有String和int
Person p = (Person)c.newInstance("张三",23);
System.out.println(p); }
}

27.06 反射(通过反射获取成员变量并使用)
 Field
  Class.getField(String)方法可以获取类中的指定字段,如果是私有的可以用getDecleadField("name")方法获取,
  再通过set(obj,"李四")方法可以设置指定对象上该字段的值,如果是私有的,需要先调用setAccessible(true)设置访问权限,
  用获取的指定的字段get(obj)可以获取指定对象中该字段的值

package day27;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import com.heima.bean.Person;
public class day27_06 {
/**
* Field
Class.getField(String)方法可以获取类中的指定字段,如果是私有的可以用getDecleadField("name")方法获取,
再通过set(obj,"李四")方法可以设置指定对象上该字段的值,如果是私有的,需要先调用setAccessible(true)设置访问权限,
用获取的指定的字段get(obj)可以获取指定对象中该字段的值
* @throws Exception
* @throws SecurityException
*/
public static void main(String[] args) throws SecurityException, Exception {
Class clazz = Class.forName("com.heima.bean.Person");
Constructor c = clazz.getConstructor(String.class,int.class); //获取有参构造。为什么是这两个.class
Person p = (Person)c.newInstance("张三",23); //通过有参构造创建对象 /*Field f = clazz.getField("name"); //获取名字字段
f.set(p,"李四"); //修改名字字段
System.out.println(p); // 无法获取,因为被私有,暴力反射*/ Field f = clazz.getDeclaredField("name"); //暴力反射获取名字字段
f.setAccessible(true); //去除私有权限
f.set(p,"李四"); //修改名字字段
System.out.println(p); }
}

暴力反射

27.07 反射(通过反射获取方法并使用)
 Method
  Class.getMethod(String,Class...)和Class.getDeclaredMethod(String,Class...)方法可以获取该类中的指定方法,
  调用invoke(Object,Object...)可以调用该方法

//前提有另建立的Person类
package day27;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import com.heima.bean.Person;
public class day27_07 {
/**
* Method
Class.getMethod(String,Class...)和Class.getDeclaredMethod(String,Class...)方法可以获取该类中的指定方法,
调用invoke(Object,Object...)可以调用该方法
* @throws Exception
* @throws SecurityException
*/
public static void main(String[] args) throws SecurityException, Exception {
Class clazz = Class.forName("com.heima.bean.Person");
Constructor c = clazz.getConstructor(String.class,int.class); //获取有参构造。给String,int赋值
Person p = (Person)c.newInstance("张三",23); //通过有参构造创建对象 Method m = clazz.getMethod("eat"); //获取eat()方法
m.invoke(p); Method m2 = clazz.getMethod("eat",int.class); //获取eat()方法并给int赋值
m2.invoke(p,10);
}
}

27.08 反射(通过反射越过泛型检查)
 案例演示:
  ArrayList<Integer>的一个对象。在这个集合中添加一个字符串数据,如何实现

package day27;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class day27_08 {
/**
* ArrayList<Integer>的一个对象。在这个集合中添加一个字符串数据,如何实现
* @throws Exception
*/
public static void main(String[] args) throws Exception {
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(111);
list.add(222); Class clazz = Class.forName("java.util.ArrayList"); //获取字节码对象
// Method m = clazz.getMethods("add",Object.class); //放入Object对象
// m.invoke(list, "abc");
System.out.println(list);
}
}

27.09 反射(通过反射写一个通用的设置)
 案例演示:
  public void setProperty(Object obj,String propertyName,Object value){}
  将obj对象中名为propertyname的属性值设置为value。
27.10 反射(练习)
27.11 反射(动态代理的概述和实现)
 1.动态代理
  在程序运行的过程中产生的现象,动态代理其实就是通过反射来生成一个代理
 2.如何生成?
  java.lang.reflect包下提供了一个Proxy类和InvocationHandler接口

/*
* 新建class文件,点击右边的add,实现一个接口InvocationHandler*/
package dongtaidaili;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public InvocationHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return null;
} }

MyInvocationHandler

------------Test类--------------
package dongtaidaili;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
UserImp ui = new UserImp();
ui.add();
ui.delete();
}
}
-----------User类----------
package dongtaidaili; public interface User { }
-----------UserImp类-----------
package dongtaidaili;
public class UserImp implements User {
public void add(){
System.out.println("权限校验");
System.out.println("添加功能");
System.out.println("日志记录");
}
public void delete(){
System.out.println("权限校验");
System.out.println("删除功能");
System.out.println("日志记录");
}
}

Test

27.12 反射(模板Template设计模式)
 1.概述:就是定义一个算法的骨架,而将具体的算法延迟到子类中来实现
 2.优缺点:
  优点:使用模板方法模式,在定义算法骨架式,可以很灵活的实现具体的算法,满足用户多变的需求
  缺点:如果算法骨架有修改的话,则需要修改抽象类
27.13 JDK5新特性(自己实现枚举类)
27.14 JDK5新特性(通过enumerate实现枚举类)
27.15 JDK5新特性(枚举类的注意事项)
27.16 JDK5新特性(枚举类的常见方法)
27.17 JDK7新特性(JDK7的6个新特性)
27.18 JDK8新特性(JDK8新特性)

上一篇:[.net 面向对象编程基础] (21) 委托


下一篇:【算法】CRF(条件随机场)