? ??“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”,如Python,Ruby是动态语 言;显然C++,Java,C#不是动态语言,但是JAVA有着一个非常突出的动态相关机制:Reflection。 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个 对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 java语言的反射机制,很多优秀的开源框架都是通过反射完成的。
语言根据执行的方式可以分为编译型和解释型,根据运行的情况可以分为静态语言和动态语言.
编译型:需要将源代码编译成机器可以解析的字节码。java? 优点:代码安全度高 缺点:执行效率偏低。
解释型:语言解析器可以直接运行源代码。代表:js python? 优点:执行效率高。缺点:代码安全度较低。
动态语言: 代码在运行期间可以动态的改变代码的结构或者变量的类型。
静态语言:代码在运行期间无法改变代码的结构或者变量的类型。
编译型语言大多属于静态语言,解释型语言动态语言偏多。
Java:准动态语言。拥有部分动态语言的特性。(反射促成了这个特征Reflection)
那什么是反射我们弄明白了,那反射的底层原理呢?
?
class就是描述类的类
接下来我们来了解class类的对象获取,总共有三种方式
package xizi.com;
import java.io.Serializable;
import java.util.Arrays;
public class Hello01Reflect {
public static void main(String[] args) throws ClassNotFoundException {
User user = new User();
user.id = 100;
user.name = "张三";
user.login();
//System.out.println(user.toString());
//开始获取类对象的信息--对象获取
Class clazz01 = user.getClass();
//开始获取类对象的信息--类进行获取
Class clazz02 = User.class;
//开始获取类对象的信息--类的全名
Class clazz03 = Class.forName("xizi.com.User");
//判断类是否只被加载一次
System.out.println(clazz01 == clazz02);
System.out.println(clazz01 == clazz03);
//Class的常见方法--获取类加载器
System.out.println(clazz01.getClassLoader());
//Class的常见方法--当前类的超类
System.out.println(clazz01.getSuperclass());
//Class的常见方法--当前类实现的接口
System.out.println(Arrays.toString(clazz01.getInterfaces()));
//Class的常见方法--获取修饰符(public , protected , private , final , static , abstract和interface )
//2的次幂数进行累加得到的结果是唯一的,通过一个值可以知道多个修饰符
System.out.println(clazz01.getModifiers());
//Class的常见方法--包和包名信息
System.out.println(clazz01.getPackage().getName());
//Class的常见方法--是否为原始数据类型(8种基本数据类型+1void)
System.out.println(clazz01.isPrimitive());
System.out.println(Integer.class.isPrimitive());
System.out.println(int.class.isPrimitive());
System.out.println(Integer.TYPE.isPrimitive());
//数组基本类型还是引用类型--引用数据类型
System.out.println(int[].class.isPrimitive());
}
}
final class User implements Serializable, Cloneable {
public int id;
public String name;
public void login() {
System.out.println();
}
}
一个类最重要的是什么呢? 当然是属性,方法,构造器
同一个包下的两个文件,下面的代码
package xizi.com;
import java.util.Date;
public class Student extends Person implements Study {
public int sid;
public String sname;
protected String sidcard;
private Date sbirthday;
public static int scount;
public Student() {
//System.out.println("Student.Student-public-0");
}
private Student(String name) {
this.sname = name;
}
public Student(int sid, String sname, String sidcard) {
this.sid = sid;
this.sname = sname;
this.sidcard = sidcard;
}
public void shello() {
System.out.println("Student.shello-没有参数");
}
public void shello(String name) {
System.out.println("Student.shello-一个参数" + name);
}
public Date shi(String name, int num) {
System.out.println("Student.shi-两个参数" + name + "--" + num);
return new Date();
}
public static void srun() {
System.out.println("Student.run--马作的的卢飞快");
}
private void shi() {
System.out.println("Student.shello-没有参数");
}
@Override
public void study() {
System.out.println("Student.study--实现接口方法");
}
}
class Person {
public int pid;
public String pname;
protected String pidcard;
private Date pbirthday;
public Person() {
System.out.println("Person.Person");
}
public void phello() {
System.out.println("Person.phello-没有参数");
}
public void phello(String name) {
System.out.println("Person.phello-一个参数" + name);
}
public Date phi(String name, int num) {
System.out.println("Person.phi-两个参数" + name + "--" + num);
return new Date();
}
public static void prun() {
System.out.println("Person.prun-跑步前进");
}
}
interface Study {
void study();
}
package xizi.com;
import java.lang.reflect.Field;
public class Hello02Field {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
//获取类
Class clazz = Class.forName("xizi.com.Student");
//获取类的属性--获取类或接口的所有可访问公共字段(public)
Field[] fs = clazz.getFields();
//Arrays.stream(fs).forEach(System.out::println);
//获取类的属性--获取类或接口声明的所有字段
Field[] dfs = clazz.getDeclaredFields();
//Arrays.stream(dfs).forEach(System.out::println);
//开始操作Field
//for (Field field : dfs) {
// System.out.println(field.getModifiers() + "--" + field.getType() + "--" + field.getName());
//}
//设置和获取属性对应的值
Student student = new Student();
Field sid = clazz.getField("sid");
Field sname = clazz.getField("sname");
Field sbirthday = clazz.getDeclaredField("sbirthday");
//属性隶属于对象
sname.set(student, "张三丰");
System.out.println(sname.get(student));
//常见错误--空指针
//sname.set(null,"张翠山");
//常见错误--变量的类型不匹配
//sname.set(student, new Date());
//sid.set(student, Integer.valueOf(128));
//静态属性隶属于类
Field scount = clazz.getField("scount");
scount.set(null, 100);
System.out.println(scount.get(null));
}
}
下面是方法?
package xizi.com;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Hello03Method {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//获取类的属性
Class clazz = Class.forName("xizi.com.Student");
//获取方法--公共方法
//Method[] ms = clazz.getMethods();
//Arrays.stream(ms).forEach(System.out::println);
//获取方法--声明方法
//Method[] dms = clazz.getDeclaredMethods();
//Arrays.stream(dms).forEach(System.out::println);
}
/**
* 方法的调用
*
* @param clazz
* @throws NoSuchMethodException
*/
private static void methodInvoke(Class clazz) throws NoSuchMethodException {
//获取指定方法--一定要记住加上形参类型列表
Method shello0 = clazz.getMethod("shello");
Method shello1 = clazz.getMethod("shello", String.class);
Method shi = clazz.getMethod("shi", String.class, int.class);
Student student = new Student();
//通过反射动态的调用方法
//shello0.invoke(student);
//shello1.invoke(student, "zhangsan");
//Date date = (Date) shi.invoke(student, "张翠山", 18);
//System.out.println(date);
//调用静态方法
//Method srun = clazz.getMethod("srun");
//srun.invoke(null);
}
/**
* 关于方法的常见错误
*
* @param clazz
* @throws NoSuchMethodException
*/
private static void methodException(Class clazz) throws NoSuchMethodException {
//常见的错误--NoSuchMethodException: com.xxxx.Student.shello(int)
//Method method = clazz.getMethod("shello", int.class);
//Method method =clazz.getMethod("hello");
//Method method = clazz.getMethod("shello", String.class);
//常见的错误--java.lang.NullPointerException
//method.invoke(null);
//常见的错误--java.lang.IllegalArgumentException: argument type mismatch
//method.invoke(new Student(), 18);
//常见的错误--java.lang.IllegalArgumentException: wrong number of arguments
//method.invoke(new Student(), "abcd", 18);
//常见的错误--java.lang.IllegalArgumentException: object is not an instance of declaring class
//method.invoke(new Object(), "abcd", 18);
//常见的错误--公共方法调用私有方法
Method method = clazz.getDeclaredMethod("shi");
//常见的错误--java.lang.IllegalAccessException: class com.xxxx.Hello03Method cannot access a member of class com.xxxx.Student with modifiers "private"
//method.invoke(new Student());
//如果设置为true,则不进行封装型修饰符的检测,那么可以进行私有方法的调用,但是大家尽量不要这么去使用
//method.setAccessible(true);
//method.invoke(new Student());
}
}
下面是构造器
package xizi.com;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Hello04Constructor {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取类
Class clazz = Class.forName("xizi.com.Student");
//获取构造器--公共的
//Constructor[] cs = clazz.getConstructors();
//Arrays.stream(cs).forEach(System.out::println);
//获取构造器--私有的
Constructor[] dcs = clazz.getDeclaredConstructors();
//Arrays.stream(dcs).forEach(System.out::println);
//for (Constructor constructor : dcs) {
// System.out.print(constructor.getModifiers() + "--" + constructor.getName() + "--");
// System.out.println(Arrays.toString(constructor.getParameterTypes()));
//}
//创建对象
Constructor constructor0 = clazz.getConstructor();
Student student = (Student) constructor0.newInstance();
Constructor constructor1 = clazz.getConstructor(int.class, String.class, String.class);
Student student1 = (Student) constructor1.newInstance(18, "name", "idcard");
System.out.println(student1.sname + "--" + student1.sidcard);
}
}
|