Java基础学习
- 一、反射
- 1.1 什么是反射
- 1.2 获取class对象
- 二、综合练习
- 2.1 保存信息
- 2.2 文件的动态创建
- 三、动态代理
- 3.1 什么是动态代理
- 3.2 创建代理
一、反射
1.1 什么是反射
反射允许对封装类的字段,方法和构造函数的信息进行编程访问
个人理解:
- 就是把一个类当中的所有有关的数据全部拿出来,获取到,便于后面的学习
利用反射可以获取到类当中的所有信息
1.2 获取class对象
class.forName("全类名")
常用于源代码阶段类名.class
常用于加载阶段对象.class
常用于运行阶段
package Myflect1;
public class flect1Dom {
public static void main(String[] args) throws ClassNotFoundException {
/*
* 获取class的三种方式
* */
//第一种 全类名:包名 + 类名 Myflect1.Student1
Class f1 = Class.forName("Myflect1.Student1");
//第二种:
Class f2 = Student1.class;
//第三种
Student1 s1 = new Student1();
Class f3 = s1.getClass();
System.out.println(f1 == f2);//true
System.out.println(f2 == f3);//true
}
}
class类中用于获取构造方法的方法
方法名称 | 说明 |
---|---|
Constructor<?>[] getConstructors(): | 返回所有公共构造方法对象的数组 |
Constructor<?>[] getDeclaredCohstructors(): | 返回所有构造方法对象的数组 |
ConstructorgetConstructor(Class<?>… parameterTypes): | 返回单个公共构造方法对象 |
ConstructorgetDeclaredConstructor(Class<?>… parameterTypes): | 返回单个构造方法对象 |
Constructor类中用于创建对象的方法:
方法名称 | 说明 |
---|---|
TnewInstance(Object…initargs): | 根据指定的构造方法创建对象 |
setAccessible(boolean flag): | 设置为true,表示取消访问检查 |
返回权限修饰符对应数值的对象:
但是如果是私有的构造方法,是需要暴力反射来解决的
暴力反射:就是临时取消权限校验
package MyReflect2;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;
import java.sql.SQLOutput;
public class reflect2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//首先获取到class对象
Class clzz = Class.forName("MyReflect2.Student2");
//获取到公有的构造方法
Constructor[] con1 = clzz.getConstructors();
for (Constructor constructor : con1) {
System.out.println(constructor);
}
System.out.println("_____________");
//获取到所有的构造方法
Constructor[] con2 = clzz.getDeclaredConstructors();
for (Constructor constructor : con2) {
System.out.println(constructor);
}
System.out.println("_____________");
//获取到某个构造方法
Constructor con3 = clzz.getDeclaredConstructor(String.class);
System.out.println(con3);
System.out.println("_____________________");
//获取到构造方法的权限修饰符对应的数值
Constructor con4 = clzz.getDeclaredConstructor(String.class, int.class);
int modifiers = con4.getModifiers();
System.out.println(modifiers);
System.out.println("_______________");
//获取构造方法当中的参数
Parameter[] parameters = con4.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
System.out.println("_____________");
//还可以利用这个创建对象
//但是如果是私有的构造方法,是需要暴力反射来解决的
//暴力反射:就是临时取消权限校验
con4.setAccessible(true);
Student2 student = (Student2) con4.newInstance("zhangsan", 23);
System.out.println(student);
}
}
利用反射获取成员变量:
class类中用于获取成员变量的方法
方法名称 | 说明 |
---|---|
FieldilgetFields(): | 返回所有公共成员变量对象的数组 |
FieldilgetDeclaredFields(): | 返回所有成员变量对象的数组 |
Field getField(String name): | 返回单个公共成员变量对象 |
Field getDeclaredField(String name): | 返回单个成员变量对象 |
Field类中用于创建对象的方法
方法 | 说明 |
---|---|
void set(Object obj,Obiect value): | 赋值Object get(Obiect obi) 获取值。 |
package MyReflect3;
import java.lang.reflect.Field;
/*
* 创建成员变量的反射
* */
public class reflect3 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
//首先创建class对象
Class clzz = Class.forName("MyReflect3.Student3");
//获取到当中公有的成员变量
Field[] f1 = clzz.getFields();
for (Field field : f1) {
System.out.println(field);
}
System.out.println("___________");
//获取所有的成员变量
Field[] f2 = clzz.getDeclaredFields();
for (Field field : f2) {
System.out.println(field);
}
System.out.println("________________");
//获取单个成员变量
Field name = clzz.getDeclaredField("name");
System.out.println(name);
System.out.println("______");
//获取到权限修饰符
int modifiers = name.getModifiers();
System.out.println(modifiers);
System.out.println("_____________");
//获取到变量当中的名字
String n = name.getName();
System.out.println(n);
//数据类型
Class type = name.getType();
System.out.println(type);
System.out.println("___________");
//获取到成员变量当中的值
Student3 s1 = new Student3("zhahngsan", 23,89);
name.setAccessible(true);
String s = (String) name.get(s1);
System.out.println(s);
//修改成员变量的值
name.set(s1,"lisi");
System.out.println(s1);
}
}
利用反射获取成员方法:
Class类中用于获取成员方法的方法
方法 | 说明 |
---|---|
Method[] getMethods(): | 返回所有公共成员方法对象的数组,包括继承的 |
Methodl[] getDeclaredMethods(): | 返回所有成员方法对象的数组,不包括继承的 |
Method getMethod(String name, Class<?>…parameterTypes): | 返回单个公共成员方法对象 |
Method getDeclaredMethodString name,Class<?>… parameterTypes): | 返回单个成员方法对象 |
Method类中用于创建对象的方法
Object invoke(Object obj, Object... args):
:运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
package MyReflect4;
import MyReflect3.Student3;
import javax.xml.transform.Source;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/*
* 创建成员方法中的反射
* */
public class reflect4 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//创建class对象
Class<?> clzz = Class.forName("MyReflect4.Student4");
//获取到公有的成员方法(包含父类的公有方法)
Method[] con1 = clzz.getMethods();
for (Method constructor : con1) {
System.out.println(constructor);
}
System.out.println("________");
//获取到所有的成员方法(不包括父类的方法)
Method[] con2 = clzz.getDeclaredMethods();
for (Method constructor : con2) {
System.out.println(constructor);
}
System.out.println("______________");
//获取单个的成员
Method eat = clzz.getDeclaredMethod("eat", String.class);
System.out.println(eat);
System.out.println("_______");
//获取到方法的修饰符
int modifiers = eat.getModifiers();
System.out.println(modifiers);
//获取到方法的名字
String name = eat.getName();
System.out.println(name);
//获取到方法的形参
int parameterCount = eat.getParameterCount();
System.out.println(parameterCount);
//获取到方法抛出的异常
Class<?>[] exceptionTypes = eat.getExceptionTypes();
for (Class<?> exceptionType : exceptionTypes) {
System.out.println(exceptionType);
}
//运行方法
Student4 s = new Student4("haisdh", 23);
eat.setAccessible(true);
//参数1:表示方法的调用者
//参数二:传输过去的实际参数
String invoke = (String) eat.invoke(s, "蜜汁汉堡");
System.out.println(invoke);
}
}
二、综合练习
2.1 保存信息
package ReflectExercises;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
/*
* 对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去
* */
public class exercise1 {
public static void main(String[] args) throws IOException, IllegalAccessException {
//首先创建对象
Student stu = new Student("张三", 23, "男");
GirlFriend girlFriend = new GirlFriend("阿瓜", 18, "好吃的", "成都");
//创建一个方法进行去实现消息的打印效果
shouinfo(stu);
shouinfo(girlFriend);
}
private static void shouinfo(Object obj) throws IOException, IllegalAccessException {
//首先获取class对象
Class clzz = obj.getClass();
//创建输出流写入对象
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt",true));
//获取到所有的消息
Field[] declaredFields = clzz.getDeclaredFields();
for (Field str : declaredFields) {
//首先临时取消权限限制,以便进行访问其名字
str.setAccessible(true);
//获取到名字
String name = str.getName();
//得到其数据
Object value = str.get(obj);
//写入数据
bw.write(name + "=" + value);
bw.newLine();
}
bw.close();
}
}
2.2 文件的动态创建
package ReflectExercises.exercise2;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.SQLOutput;
import java.util.Properties;
/*
* 反射可以跟配置文件结合的方式,动态的创建对象,并调用方法
* */
public class exercise2 {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 1/读取配置文件的信息
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("E:\\Java文件夹\\Myflects\\src\\ReflectExercises\\exercise2\\prop.properties");
prop.load(fis);
fis.close();
// 2. 获取全类名和方法名
String className = (String) prop.get("classname");
String methodName = (String) prop.get("method");
//创建class对象
Class clzz = Class.forName(className);
//获取到构造方法
Constructor con = clzz.getDeclaredConstructor();
//利用空参创建对象
Object o = con.newInstance();
System.out.println(o);
//获取成员方法并且运行
Method method = clzz.getDeclaredMethod(methodName);
method.setAccessible(true);
method.invoke(o);
}
}
常见方法:
get:
获取
Constructor:构造方法
Field:成员变量
Method:方法
set:设置
Parameter:参数
Modifiers:修饰符
Declared:私有的
三、动态代理
3.1 什么是动态代理
想象图
简单理解就是通过代理去添加其他想要添加的功能,还不用去修改原先的代码,以防出错
通过接口的方式把所有的方法进行传输代理
总结:
- 为什么需要代理?
代理可以无侵入式的给对象增强其他的功能
调用者------>代理--------->对象- 代理长什么样?
代理里面就是对象要被代理的方法
- Java通过什么来保证代理的样子?
实现同一个接口通过接口保证,后面的对象和代理需要接口中就是被代理的所有方法
3.2 创建代理
方法 | 说明 |
---|---|
public static Obiect newProxyInstance(Classloader loader, Class<?>i intenfaces, InvocationHandler h) | 提供为对象产生代理对象的方法 |
参数一:用于指定用哪个类加载器,去加载生成的代理类
参数二:指定接口,这些接口用于指定生成的代理长什么,也就是有哪些方法
参数三:用来指定生成的代理对象要干什么事情
创建的代理:
package ReflectExercises.exercise3;
/*
* 创建代理
* */
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyUtil {
/*
* 方法作用:给明星对象,创建一个代理
*
*形参:被代理的对象
*
* 返回值:给明星创建的代理
*
*
* 需求:
外面的人想要大明星唱一首歌
1。获取代理的对象
代理对象 = ProxyUti.createProxy(大明星的对象);
* 2。再调用代理的唱歌方法
代理对象.唱歌的方法("只因你太美");
* */
public static Star createProxy(Star bigstar){
Star star = (Star) Proxy.newProxyInstance(
ProxyUtil.class.getClassLoader(),
new Class[]{Star.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/*
* 参数一:表示需要代理的对象
* 参数二:表示执行的方法
* 参数三:表示当中的参数
* */
if ("sing".equals(method.getName())){
System.out.println("准备话筒,收钱");
} else if ("dance".equals(method.getName())) {
System.out.println("准备舞台,收钱");
}
return method.invoke(bigstar,args);
}
}
);
return star;
}
}
接口:
package ReflectExercises.exercise3;
public interface Star {
public abstract String sing(String name);
public abstract void dance();
}
大明星对象:
package ReflectExercises.exercise3;
public class BigStar implements Star {
private String name;
public BigStar() {
}
public BigStar(String name) {
this.name = name;
}
@Override
public String sing(String name){
System.out.println(getName()+"正在唱"+name);
return "谢谢";
}
@Override
public void dance(){
System.out.println(getName()+"正在跳舞");
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
public String toString() {
return "BigStar{name = " + name + "}";
}
}
测试类:
package ReflectExercises.exercise3;
public class Test {
public static void main(String[] args) {
//创建打明星对象
BigStar bigStar = new BigStar("小鸡哥");
//创建代理
Star proxy = ProxyUtil.createProxy(bigStar);
//调用方法
String str = proxy.sing("阿里嘎多");
System.out.println(str);
proxy.dance();
}
}