- 反射概述
- Java的反射机制是在运行状态中, 对于任意一个类, 都能知道这个类的所有属性和方法
- 对于任意一个对象, 都能够调用它的任意一个方法和属性
- 这种动态获取信息以及动态调用对象的方法的功能称为Java语文的反射机制
- 想要解剖一个类, 必需先要获取到该类的字节码文件对象
- 而解剖使用的就是Class类中的方法, 所以先要获取到每一个字节码文件对应的Class类型的对象
- 反射的三种方式
- Object烦的getClass()方法, 判断2个对象是否是同一个字节码文件
- 静态属性class, 锁对象(Person.class)
- Class类中静态方法forName(), 读取配置文件
import com.lizicai.bean.Person;
public class Demo1_Reflect {
public static void main(String[] args) throws ClassNotFoundException {
Class clazz1 = Class.forName("com.lizicai.bean.Person");
Class clazz2 = Person.class;
Person p = new Person();
Class clazz3 = p.getClass();
System.out.println(clazz1 == clazz2);
System.out.println(clazz2 == clazz3);
}
}
反射(Class.forName()读取配置文件举例)#
import java.io.*;
public class Demo2_Reflect {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
// nouseReflect();
String str = null;
BufferedReader br = new BufferedReader(new FileReader("config.properties"));
str = br.readLine();
Class clazz = Class.forName(str);
Fruit f = (Fruit) clazz.newInstance();
Juier j = new Juier();
j.run(f);
}
private static void nouseReflect() {
Juier j = new Juier();
Apple apple = new Apple();
j.run(apple);
j.run(new Orange());
}
}
interface Fruit{
public void squeeze();
}
class Apple implements Fruit {
@Override
public void squeeze(){
System.out.println("苹果汁");
}
}
class Orange implements Fruit{
@Override
public void squeeze(){
System.out.println("橙汁");
}
}
class Juier{
public void run(Fruit fruit){
fruit.squeeze();
}
public void run(Orange orange){
orange.squeeze();
}
}
com.lizicai.reflect.Orange
通过反射获取带参构造方法并使用#
- 构造函数必须public, 否则报NoSuchMethodException 异常.
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Demo3_Reflect {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class clazz = Class.forName("com.lizicai.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);
}
}
public class Person {
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
@Override
public int hashCode() {
return super.hashCode();
}
@Override
public String toString() {
return this.getName() + this.getAge();
}
}
通过反射获取成员变量并使用#
import com.lizicai.bean.Person;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class Demo4_Reflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class clazz = Class.forName("com.lizicai.bean.Person");
Constructor c = clazz.getConstructor(String.class, int.class);
Person p = (Person) c.newInstance("张三",23);
// Field f = clazz.getField("name");
// 暴力反射
Field f = clazz.getDeclaredField("name");
// 去除私有权限
f.setAccessible(true);
f.set(p,"李四");
System.out.println(p);
}
}
通过反射获取方法并使用#
import com.lizicai.bean.Person;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Demo5_Reflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, NoSuchFieldException, InvocationTargetException {
Class clazz = Class.forName("com.lizicai.bean.Person");
Constructor c = clazz.getConstructor(String.class, int.class);
Person p = (Person) c.newInstance("张三",23);
Method m = clazz.getMethod("eat");
m.invoke(p);
Method m2 = clazz.getMethod("eat", int.class);
m2.invoke(p,10);
}
}
通过反射越过泛型检查#
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class Test1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
Class clazz = Class.forName("java.util.ArrayList");
Method m = clazz.getMethod("add",Object.class);
m.invoke(list,"test");
System.out.println(list);
}
}
通过反射写一个通用的设置某个对象的某个属性为指定的值#
import java.lang.reflect.Field;
public class Tool {
public void setProperty(Object obj, String propertyName, Object value) throws NoSuchFieldException, IllegalAccessException {
Class clazz = obj.getClass();
Field f = clazz.getDeclaredField(propertyName);
f.setAccessible(true);
f.set(obj,value);
}
}
import com.lizicai.bean.Person;
public class Test2 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Person p = new Person("小明",23);
System.out.println(p);
Tool t = new Tool();
t.setProperty(p,"name","小红");
System.out.println(p);
}
}
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test3 {
public static void main(String[] args) throws IOException, ClassNotFoundException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
File file = new File("demo.properties");
BufferedReader br = new BufferedReader(new FileReader(file));
String clazzName = br.readLine();
br.close();
Class clazz = Class.forName(clazzName);
DemoClass dc = (DemoClass) clazz.newInstance();
Method m = clazz.getMethod("run");
m.invoke(dc);
}
}
public class DemoClass {
public void run(){
System.out.println("大王叫我来巡山");
}
}
com.lizicai.test.DemoClass
动态代理的概述和实现#
public interface User {
public void add();
public void delete();
}
public class UserImp implements User{
@Override
public void add() {
// System.out.println("权限校验");
System.out.println("添加");
// System.out.println("日志记录");
}
@Override
public void delete() {
// System.out.println("权限校验");
System.out.println("删除");
// System.out.println("日志记录");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("权限检验");
method.invoke(target,args);
System.out.println("日志记录");
return null;
}
}
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
User ui = new UserImp();
ui.add();
ui.delete();
MyInvocationHandler m = new MyInvocationHandler(ui);
User u = (User) Proxy.newProxyInstance(ui.getClass().getClassLoader(), ui.getClass().getInterfaces(),m);
u.add();
u.delete();
}
}
模版(Template)设计模式概述和使用#
- 模版设计模式概述
- 模版方法模式就是定义一个算法模版, 而将具体的算法延迟到子类中实现
- 优点 缺点
- 使用模版方法模式, 在定义骨架的同时, 可以很灵活实现具体的方法, 满足用户灵活多变的需求
- 如果算法有修改, 则需要修改抽象类
public class Demo1_Template extends TestTime{
public static void main(String[] args) {
Demo1_Template d = new Demo1_Template();
System.out.println(d.getTime());
}
@Override
public void code() {
for(int i=0;i<100000;i++){
System.out.println(i);
}
}
}
abstract class TestTime{
final public long getTime(){
long start = System.currentTimeMillis();
code();
long end = System.currentTimeMillis();
return end - start;
}
public abstract void code();
}
自己实现枚举类#
- 概述
- 是指将变量的值一一列举出来, 变量的值仅限于列举出来的值的范围内
- 单例模式, 只有一个实例
- 多例类就是一个类有多个实例, 但不是无限多个实例, 是有限个数的实例, 这才是枚举类.
- 枚举类有下例3种形式
public class Week {
final static Week MON = new Week();
final static Week TUE = new Week();
final static Week WED = new Week();
private Week(){}
}
public class Week2 {
final static Week2 MON = new Week2("星期一");
final static Week2 TUE = new Week2("星期二");
final static Week2 WED = new Week2("星期三");
String name;
private Week2(String name){
this.name = name;
}
@Override
public String toString() {
return this.name;
}
}
public abstract class Week3 {
final static Week3 MON = new Week3("星期一"){
@Override
public void show() {
System.out.println("星期一");
}
};
final static Week3 TUE = new Week3("星期二"){
@Override
public void show() {
System.out.println("星期二");
}
};
final static Week3 WED = new Week3("星期三") {
@Override
public void show() {
System.out.println("星期三");
}
};
String name;
private Week3(String name){
this.name = name;
}
@Override
public String toString() {
return this.name;
}
public abstract void show();
}
public class Demo1_Enum {
public static void main(String[] args) {
Week mon = Week.MON;
System.out.println(mon);
Week2 Mon = Week2.MON;
Week2 Tue = Week2.TUE;
Week2 Wed = Week2.WED;
System.out.println(Mon);
System.out.println(Tue);
System.out.println(Wed);
Week3 MON = Week3.MON;
Week3 TUE = Week3.TUE;
Week3 WED = Week3.WED;
MON.show();
TUE.show();
WED.show();
}
}
通过enum实现枚举类#
public enum Week {
MON,TUE,WED;
}
public enum Week2 {
MON("星期一"),TUE("星期二"),WED("星期三");
private String name ;
Week2(String name){
this.name = name;
}
public String getName() {
return name;
}
}
public enum Week3 {
MON("星期一"){
@Override
public void show() {
System.out.println("星期一");
}
},TUE("星期二"){
@Override
public void show() {
System.out.println("星期二");
}
},WED("星期三"){
@Override
public void show() {
System.out.println("星期三");
}
};
private String name ;
Week3(String name){
this.name = name;
}
public String getName() {
return name;
}
public abstract void show();
}
public class Demo1_Enum {
public static void main(String[] args) {
Week mon = Week.MON;
Week tue = Week.TUE;
System.out.println(mon);
System.out.println(tue);
Week2 Mon = Week2.MON;
Week2 Tue = Week2.TUE;
System.out.println(Mon);
System.out.println(Tue.getName());
Week3 MON = Week3.MON;
Week3 TUE = Week3.TUE;
Week3 WED = Week3.WED;
System.out.println(MON);
System.out.println(TUE.getName());
System.out.println(WED.getName());
}
}
switch 使用枚举#
public static void demo1(){
Week2 MON = Week2.TUE;
switch (MON){
case MON:
System.out.println("星期一");
break;
case TUE:
System.out.println("星期二");
break;
case WED:
System.out.println("星期三");
break;
}
}
常用的枚举方法#
- public final int ordinal() 获取枚举的位置
- public final int compareTo(E o) 比较枚举位置, 返回差
- public final String name() 获取枚举实例的名字
- public static <T extends Enum> T valueOf(Class enumType, String name) 字节码对象获取枚举项
- values 获取枚举的数组
public class Demo2_Enum {
public static void main(String[] args) {
Week2 mon = Week2.MON;
Week2 tue = Week2.TUE;
Week2 wed = Week2.WED;
System.out.println(mon.ordinal());
System.out.println(tue.ordinal());
System.out.println(wed.ordinal());
System.out.println(mon.compareTo(tue));
System.out.println(mon.compareTo(wed));
System.out.println(mon.name());
System.out.println(tue.name());
System.out.println(mon);
System.out.println(tue.toString());
// 字节码对象获取枚举项
Week2 TUE = Week2.valueOf(Week2.class,"TUE");
System.out.println(TUE);
Week2[] arr = Week2.values();
for(Week2 w:arr){
System.out.println(w);
}
}
}
JDK 1.7 新增内容#
- switch支持字符串
- 异常catch多个异常, 用|隔开
- try-whith-resources 自动关流
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class Demo3_AutoClose {
public static void main(String[] args) {
File file = new File("config.properties");
//资源放在try()中, 会自动关闭资源, 不用在finally 中关闭了
try ( FileInputStream fis = new FileInputStream(file)){
int b;
while ( ( b = fis.read() ) != -1){
System.out.println(b);
}
} catch (IOException e){
System.out.println(e.getMessage());
}
}
}
JDK 1.8 新增内容#
- 接口可以支持default修饰, 有方法体
- 接口也可以有静态方法了
- 内部类可访问的变量默认是final修饰
public class Demo4_JKD18 {
// JDK1.8新特性
public static void main(String[] args) {
Demo d = new Demo();
d.show();
Inter.test();
d.run();
}
}
interface Inter{
public default void show(){
System.out.println("显示");
}
public static void test(){
System.out.println("测试");
}
}
class Demo implements Inter{
public void run(){
// num 默认是final
int num = 20;
class Inner{
public void fun(){
System.out.println("fun");
}
}
Inner i = new Inner();
i.fun();
}
}