动态语言 是一类在运行时可以改变其结果的语言:例如新的函数,对象,甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化,通俗的说就是代码运行时,代码可以根据某些条件改变自身结构. 主要动态语言: Object-c, C#,JavaScript,php,python等 静态语言 与动态语言相对应,运行时结果不可变的语言就是静态语言,如java,c,c++ java不是动态语言,但java称之为准"动态语言".即java有一定的动态性,我们可以利用反射机制获得动态语言的特性.java的动态机制让编程更加灵活!
Reflection是java被称为动态语言的关键,反射机制永许在执行期借助Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性以及方法. Class c = Class.forName(“java.lang.String”) 加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结果信息.我们可以通过这个对象看到类的结果.这个对象就像一面镜子,透过这个镜子看到类的结构,所以我们形象的称之为:反射. 正常方式:引入需要的"包类"名称⇒ 通过new 实例化 ⇒ 取得实例化对象 反射方式: 实例化对象 =>getClass()方法 => 取得完整的"包类"名称
优点 : 可以实现动态创建对象和编译,体现出很大的灵活性. 缺点:对性能有影响.使用反射基本上是一种解释操作,我们需要去告诉JVM,我们希望做什么并且它满足我们的要求.这类操作总是慢于直接执行相同的操作.
java.lang.Class: 代表一个类. java.lang.reflect.Method:代表类的方法 java.lang.reflect.Field:代表类的方法 java.lang.reflect.Constructor:代表类的方法
在Object类中定义了以下的方法,此方法将被所有子类继承 public final Class getClass() 以上的方法返回值的类型是一个Class类,此类是java反射的源头,实际上从程序的运行结果很好得理解,看出可以通过反射求出一个类的名称.
代码演示
package com.kuang; public class test1 { public static void main(String[] args) throws ClassNotFoundException { Person person = new Student(); System.out.println(person.name); // 方式一 通过对象获得 Class c1 = person.getClass(); System.out.println(c1.hashCode()); // 方式二 通过名称获得 Class c2 = Class.forName("com.kuang.Student"); System.out.println(c2.hashCode()); // 方式三 通过类名活动 Class c3 = Student.class; System.out.println(c3.hashCode()); // 通过子类获得父类 Class c4 = c3.getSuperclass(); System.out.println(c4.hashCode()); // 基本类型都有内置属性 Type Class c5 = Integer.TYPE; System.out.println(c5); } } class Person{ public String name; public Person() { } public Person(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } } class Student extends Person{ public Student() { this.name = "学生"; } } class Teacher extends Person{ public Teacher (){ this.name = "教师"; } }a) 若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高 Class clazz = Person.class; b)已知某个类的实例,调用该实例的getClass()方法获取Class对象 Class clazz = person.getClass(); c)已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出 ClassNotFoundException Class clazz = Class.forName(“demo01.Student”); d) 基本数据类型可以直接用类名.Type e) 还可以利用ClassLoader下面会详解.
class: 外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类. interface: 接口 []: 数组 enum: 枚举 annotation : 注解@Interface primitive type : 基本数据类型 void
package com.kuang; import java.lang.annotation.ElementType; public class test2 { public static void main(String[] args) { Class c1 = Object.class; // 类 Class c2 = Comparable.class; //接口 Class c3 = String[].class; // String一维数组 Class c4 = int[][].class; // int 二维数组 Class c5 = Override.class; // 注解 Class c6 = ElementType.class; // 枚举 Class c7 = Integer.class; // 基本数据类型 Class c8 = void.class; // void Class c9 = Class.class; // Class System.out.println(c1); System.out.println(c2); System.out.println(c3); System.out.println(c4); System.out.println(c5); System.out.println(c6); System.out.println(c7); System.out.println(c8); System.out.println(c9); } } 运行结果 class java.lang.Object interface java.lang.Comparable class [Ljava.lang.String; class [[I interface java.lang.Override class java.lang.annotation.ElementType class java.lang.Integer void class java.lang.Class了解:类的加载过程
类加载器的作用
通过反射获取运行时类的完整结构 Field , Method, Constructor,Superclass,Interface,Annotation 实现的全部接口 所继承的父类 全部的构造器 全部的方法 全部的Field 注解 … 代码 体现下面
package com.kuang; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class test8 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException { Class c1 = Class.forName("com.kuang.pojo.User"); System.out.println(c1.getName());//获得包名+ 类名 com.kuang.pojo.User System.out.println(c1.getSimpleName());//获得类名 User //获得类的属性. Field[] fields = c1.getFields();//只能得到public公共的属性. //找到全部属性 Field[] fields1 = c1.getDeclaredFields(); for(Field f:fields1){ System.out.println(f); /* private java.lang.String com.kuang.pojo.User.name private int com.kuang.pojo.User.id private int com.kuang.pojo.User.age * */ } System.out.println("=========================="); //获得指定属性的值 Field field = c1.getDeclaredField("name");//private java.lang.String com.kuang.pojo.User.name System.out.println(field); //获得类的方法 System.out.println("==============="); //获得方法 获得本类及其父类public 公共的方法. Method[] methods = c1.getMethods(); for (Method m1: methods){ System.out.println(m1); /* 不但获得本类的公共方法,还活动了Object的方法了. public java.lang.String com.kuang.pojo.User.toString() public java.lang.String com.kuang.pojo.User.getName() public int com.kuang.pojo.User.getId() public void com.kuang.pojo.User.setName(java.lang.String) public int com.kuang.pojo.User.getAge() public void com.kuang.pojo.User.setAge(int) public void com.kuang.pojo.User.setId(int) public final void java.lang.Object.wait() throws java.lang.InterruptedException public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException public boolean java.lang.Object.equals(java.lang.Object) public native int java.lang.Object.hashCode() public final native java.lang.Class java.lang.Object.getClass() public final native void java.lang.Object.notify() public final native void java.lang.Object.notifyAll() * */ } System.out.println("----------------------"); // 获得本类所有的方法. Method[] declaredMethods = c1.getDeclaredMethods(); for (Method m2:declaredMethods){ System.out.println(m2); /* public java.lang.String com.kuang.pojo.User.toString() public java.lang.String com.kuang.pojo.User.getName() public int com.kuang.pojo.User.getId() public void com.kuang.pojo.User.setName(java.lang.String) private void com.kuang.pojo.User.test() public int com.kuang.pojo.User.getAge() public void com.kuang.pojo.User.setAge(int) public void com.kuang.pojo.User.setId(int) * */ } System.out.println("=========="); // 获得指定的方法 // 因为方法有重载 所以需要参数 Method m3 = c1.getMethod("getName",null); Method m4 = c1.getMethod("setName",String.class); System.out.println(m3); System.out.println(m4); /* * public java.lang.String com.kuang.pojo.User.getName() public void com.kuang.pojo.User.setName(java.lang.String) * */ System.out.println("---------------===================="); Method m5 = c1.getDeclaredMethod("getName",null); Method m6 = c1.getDeclaredMethod("setName",String.class); System.out.println(m5); System.out.println(m6); // public java.lang.String com.kuang.pojo.User.getName() // public void com.kuang.pojo.User.setName(java.lang.String) System.out.println("===============------------------======="); //获得构造器 Constructor[] constructors = c1.getConstructors(); for (Constructor constructor:constructors){ System.out.println(constructor); //public com.kuang.pojo.User() //public com.kuang.pojo.User(java.lang.String,int,int) } System.out.println("=========================="); Constructor[] declaredConstructors = c1.getDeclaredConstructors(); for (Constructor constructor:declaredConstructors){ System.out.println(constructor); //public com.kuang.pojo.User() //public com.kuang.pojo.User(java.lang.String,int,int) } System.out.println("=========================="); // 获得指定的构造器 Constructor constructor = c1.getConstructor(String.class, int.class, int.class); System.out.println(constructor);//public com.kuang.pojo.User(java.lang.String,int,int) // 后面没有参数 就是获得无参的构造器. Constructor constructor1 = c1.getConstructor(); System.out.println(constructor1); // public com.kuang.pojo.User() } }代码演示如下
package com.kuang; import com.kuang.pojo.User; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.List; import java.util.Map; // 反射获得泛型 public class Test11 { public void test01(Map<String,User> map,List<String> list){ System.out.println("test01"); } public Map<String,User> test02(){ System.out.println("test02"); return null; } public static void main(String[] args) throws NoSuchMethodException { //测试方法1 想拿到泛型 要先拿到方法. Method test01 = Test11.class.getDeclaredMethod("test01", Map.class, List.class); Type[] genericParameterTypes = test01.getGenericParameterTypes(); // 获得泛型类型的数组 for (Type genericParameterType : genericParameterTypes) { System.out.println(genericParameterType); //java.util.Map<java.lang.String, com.kuang.pojo.User> // java.util.List<java.lang.String> if (genericParameterType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();// 获得真实的参数类型 for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); //class java.lang.String // class com.kuang.pojo.User //class java.lang.String } } } System.out.println("=================="); //测试方法2 想拿到泛型 要先拿到方法. Method test02 = Test11.class.getDeclaredMethod("test02", null); Type genericReturnType = test02.getGenericReturnType(); // 获得返回值类型. System.out.println(genericReturnType);//返回值类型只有一个. java.util.Map<java.lang.String, com.kuang.pojo.User> if(genericReturnType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); //class java.lang.String //class com.kuang.pojo.User } } } }代码演示
package com.kuang; import java.lang.annotation.*; import java.lang.reflect.Field; // 练习反射操作注解 public class Test12 { public static void main(String[] args) throws NoSuchFieldException { Class c1 = Student2.class; // 通过反射获得注解 Annotation[] annotations = c1.getAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation); //@com.kuang.TableAnnotation(value=db_student) } //获得指定类上的注解的value的值. TableAnnotation tableAnnotation = (TableAnnotation) c1.getAnnotation(TableAnnotation.class); System.out.println(tableAnnotation.value());//db_student // 获得类中指定字段(属性)的注解 Field id = c1.getDeclaredField("id"); FieldAnnotation annotation = id.getAnnotation(FieldAnnotation.class); System.out.println(annotation.columnName());//db_id System.out.println(annotation.type());//int System.out.println(annotation.length());//10 } } @TableAnnotation("db_student") // 比如这个数据库的名字叫db_student 来注解. class Student2{ @FieldAnnotation(columnName = "db_name",type="varchar",length = "3") // 注明,它是db_的id, 类型int ,长度10位 private String name; @FieldAnnotation(columnName = "db_id",type="int",length = "10") // 注明,它是db_的id, 类型int ,长度10位 private int id; @FieldAnnotation(columnName = "db_age",type="int",length = "10") // 注明,它是db_的id, 类型int ,长度10位 private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", id=" + id + ", age=" + age + '}'; } } // 自定义的注解 //类名的注解 @Target(ElementType.TYPE) // 作用在类上 @Retention(RetentionPolicy.RUNTIME) // 运行级别 @interface TableAnnotation{ String value(); } // 属性的注解 @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface FieldAnnotation{ String columnName(); String type(); String length(); }