------Java培训、Android培训、iOS培训、.Net培训、期待与您交流!-----
一、反射概述
反射简介
反射机制是在程序运行状态,对于任意一个类,都可以知道这个类的所有属性和方法,对于任意一个对象,都可以调用其方法和属性。
总而言之,反射是动态获取类信息和调用对象属性方法的一种机制。
什么时候使用反射?(反射大大提高了程序的扩展性)
对于一个已经完成的程序,会提供一个Properties配置文件,我们可以通过读取配置文件获得类名字段,通过反射的方式获得这个类并创建实例,
从而扩展功能。
类的加载
类的加载分为三个步骤:
A.加载 将.class文件读入内存,并创建Class对象
B.连接 验证:内部结构是否正确,并和其他类协调一致 准备:为静态成员分配内存 解析:将二进制符号引用替换为直接引用
C.初始化 类的初始化
加载时机:创建类的示例,访问修改类的静态属性,调用类的静态方法,反射方式获取Class对象,初始化子类
反射的三种方式
A.Class clazz = Person.class
B.Class clazz = new Person().getClass
C.Class clazz = Class.forName("com.fanfan.Person");
二、Class类,反射的基石
Class概述:
java类用于描述某一类事物,将其共性向上抽取并封装。而Class类则将java类的共性向上抽取,封装。即:Class类是java类的类。其对象对应字节码文件:Xxx.class
Class类的成员属性:
field(字段)
constructor(构造函数)
method(方法)
Class类的方法:
static Class forName(String className)
返回与给定字符串名的类或接口的相关联的Class对象。
Class getClass()
返回的是Object运行时的类,即返回Class对象即字节码对象
Constructor getConstructor()
返回Constructor对象,它反映此Class对象所表示的类的指定公共构造方法。
Field getField(String name)
返回一个Field对象,它表示此Class对象所代表的类或接口的指定公共成员字段。
Field[] getFields()
返回包含某些Field对象的数组,表示所代表类中的成员字段。
Method getMethod(String name,Class… parameterTypes)
返回一个Method对象,它表示的是此Class对象所代表的类的指定公共成员方法。
Method[] getMehtods()
返回一个包含某些Method对象的数组,是所代表的的类中的公共成员方法。
String getName()
以String形式返回此Class对象所表示的实体名称。
String getSuperclass()
返回此Class所表示的类的超类的名称
boolean isArray()
判定此Class对象是否表示一个数组
boolean isPrimitive()
判断指定的Class对象是否是一个基本类型。
T newInstance()
创建此Class对象所表示的类的一个新实例。
示例:通过反射获取对象。
package com.fan.testmain; public class Test2 { public static void main(String[] args) throws Exception { String name = "com.fan.testmain.Test1"; Class clazz = Class.forName(name); Test1 test1 = (Test1)clazz.newInstance(); } }
Constructor类
获取构造方法:
得到这个类的所有构造方法:如得到上面示例中Person类的所有构造方法
Constructor[] cons = Class.forName(“com.fan.Person”).getConstructors();
获取某一个构造方法:
Constructor con=Person.class.getConstructor(String.class,int.class);
创建实例对象:
通常方式:Person p = new Person(“mimi”,30);
反射方式:Person p= (Person)con.newInstance(“mimi”,30);
利用Constructor类来创建类实例的好处是可以指定构造函数,而Class类只能利用无参构造函数创建类实例对象。
public class Test2 { public static void createPersonClass_2() throws Exception{ //获取Person类的Class对象 String className="com.fanfan.Person"; Class clazz=Class.forName(className); //获取指定构造函数的类实例 Constructor con=clazz.getConstructor(String.class,int.class); Person p=(Person) con.newInstance("lisi",30); System.out.println(p.toString()); } }
Field类
Field类代表某个类中一个成员变量
方法
Field getField(String s);//只能获取公有和父类中公有
Field getDeclaredField(String s);//获取该类中任意成员变量,包括私有
setAccessible(ture);//如果是私有字段,要先将该私有字段进行取消权限检查的能力。暴力访问。
set(Object obj, Object value);//将指定对象变量上此Field对象表示的字段设置为指定的新值。
Object get(Object obj);//返回指定对象上Field表示的字段的值。
示例:
public class Test2 { public static void main(String[] args) throws Exception { Class clazz = Class.forName("com.fan.testmain.Person");//获取Person.class Constructor cons = clazz.getConstructor(String.class,int.class); //获取Person类的构造方法 Person p1 = (Person)cons.newInstance("葫芦娃",18); //new Person(); System.out.println(p1); Field f1 = clazz.getDeclaredField("name"); //new Field对象.描述Person类的String name字段 f1.setAccessible(true); //暴力访问 f1.set(p1, "孙悟空"); //修改对象p1的name值 Field f2 = clazz.getDeclaredField("age"); f2.setAccessible(true); f2.set(p1, 1000); System.out.println(p1); } }
Method类
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)
示例:
class EdisonChen extends Person { public EdisonChen(String name, int age) { super(name, age); // TODO Auto-generated constructor stub } //子类speak方法 public void speak(String line) { System.out.println("大家好我叫"+this.name+line); } //打印num*num乘法表 public void printTable(int num) { for(int i = num; i > 0; i--) { for(int j = 1; j <= i; j++) { System.out.print(i+"*"+j+" = "+i*j+"\t"); } System.out.println(); } } }
public class Test2 { public static void main(String[] args) throws Exception { //获取Class的对象(EdisonChen。class)并获取其构造方法(带参数); String personPath = "com.fan.testmain.EdisonChen"; Class clazz = Class.forName(personPath); Constructor cons = clazz.getConstructor(String.class,int.class); //多态,创建对象 Person p1 = (EdisonChen)cons.newInstance("陈冠希",10); //获取并执行speak()方法 Method m1 = clazz.getMethod("speak", String.class); m1.invoke(p1, "你记得我吗"); //获取并执行printTable()方法; Method m2 = clazz.getMethod("printTable",int.class); m2.invoke(p1, 9); } }
三、Template设计模式
A模版设计模式概述
模版方法模式就是定义一个算法的骨架,而将具体的算法延迟到子类中来实现
B:优点和缺点
a:优点使用模版方法模式,在定义算法骨架的同时,可以很灵活的实现具体的算法,满足用户灵活多变的需求
b:缺点
如果算法骨架有修改的话,则需要修改抽象类
public class Test2 { public static void main(String[] args) throws Exception { GetII getii = new GetII(); getii.run(); } } abstract class GetI { public void run () { //算法骨架 Long startTime = System.currentTimeMillis() ; code(); // 由子类具体实现 Long EndTime = System.currentTimeMillis(); System.out.println(EndTime - startTime); } public abstract void code(); //抽象方法 } class GetII extends GetI { public void code() { for(int i = 0 ; i<100;i++) { System.out.println(i); } } }
四、JDK新特性
JDK5.0
泛型
自动拆装箱
互斥锁
可变参数
静态导入
增强for循环
枚举
public enum Colour { RED("红色"),WHITE("白色"),YELLOW("黄色"),GREEN("绿色"); private String name; private Colour(String name) { this.name = name; } public String toString() { return name; } }
JDK7.0
二进制字面量 0b0010
数字字面量下划线 1000_000(1000,000)
switch语句可以用字符串
多个异常的catch合并,每个异常用或
try--with--resource语句
JDK8.0
接口中的方法可以拥有方法体,但是非静态方法一定要用default修饰
局部内部类访问类中成员时,不必加final修饰