反射 Reflection
反射机制允许程序在执行期间借助于Reflection API,取得任何类的内部信息,并且能直接操作任意对象的内部属性和方法。
加载完类之后,在堆内存中就会产生一个Class类型的对象(一个类只有一个),这个对象就包含了完整的类信息。我们可以通过这个对象看清类的结构,我们称之为反射。
静态语言:C C++ Java
动态语言:在运行时可以改变内部结构JavaScript PHP C# Erlang等等
其实java应该是准动态语言,因为它可以通过反射机制,实现一些类似于动态语言的一些操作。
如何看待反射和封装性?
首先这两个技术并不矛盾,首先封装性是我们的权限修饰符,它更多的是一种提示作用,也可以这样想就是说java希望我们不要在类的外部使用私有方法等等,但是反射可以这样做。总而言之就是可以但不建议。
什么时候使用反射?什么时候使用new 构造器?
有时候我们在编译的时候,无法确定创建哪个类的对象,此时就要使用反射;相对应的,如果在编译之前我们就已经知道使用哪个类的对象了,就可以直接通过构造器 new对象。
比如我们在在网站的时候,启动了项目,我们此时不知道用户会执行那个操作,他有可能会登录,有可能会注册,此时就可以使用反射了。
Class类
程序通过javac.exe命令行以后,会生成一个或者多个字节码文件(.class结尾)
接着我们使用java.exe命令对某个字节码文件进行解释运行,相当于将某个字节码文件加载到内存中,这个就称为运行时类。这个运行时类就是Class的一个对象。我们也可以这样理解类其实也是对象(Class这个类的对象)。所以说java中万事万物皆对象!
类的加载:
哪些类型可以有Class对象:
类的加载器:
通过getParent()方法获取上一层的类加载器对象。
获取Class实例的获取
import org.junit.Test;
public class ClassTest {
@Test
public void test01() {
//方式1 调用运行时类的属性
Class class1=BigPerson.class;
System.out.println(class1);
//方式2 通过运行时类的对象的方法
BigPerson person=new BigPerson();
Class class2=person.getClass();
System.out.println(class2.getName());
//方式3 Class的静态方法
try {
Class class3=Class.forName("BigPerson");//全限定名称
System.out.println(class3);
}catch (ClassNotFoundException e){
e.printStackTrace();
}
//方式4 通过类的加载器
try {
ClassLoader classLoader=ClassTest.class.getClassLoader();
Class class4=classLoader.loadClass("BigPerson");
System.out.println(class4);
}catch (ClassNotFoundException e){
e.printStackTrace();
}
}
}
class BigPerson{
private String name;
private int age;
public String description;
public BigPerson(String name, int age, String description) {
this.name = name;
this.age = age;
this.description = description;
}
public BigPerson() {
}
private BigPerson(String name) {
this.name = name;
}
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;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
private String show(String id){
System.out.println("你的id是:"+id);
return id;
}
private void show(){
System.out.println("你的id是:"+"123");
}
}
读取配置文件的方式:
@Test
public void test02() throws Exception {
Properties properties1=new Properties();
InputStream inputStream=new FileInputStream("lala.properties");
properties1.load(inputStream);
String name1 = properties1.getProperty("name");
String password1 = properties1.getProperty("password");
String age1=properties1.getProperty("age");
Properties properties2=new Properties();
ClassLoader classLoader=ClassTest.class.getClassLoader();
InputStream resourceAsStream = classLoader.getResourceAsStream("lala1.properties");
properties2.load(resourceAsStream);
String name2 = properties2.getProperty("name");
String password2 = properties2.getProperty("password");
String age2=properties2.getProperty("age");
System.out.println(name1+" "+password1+" "+age1);
System.out.println(name2+" "+password2+" "+age2);
}
通过反射构造类的实例
import org.junit.Test;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Properties;
public class ClassTest {
@Test
public void test03() throws
IllegalAccessException,
InstantiationException,
ClassNotFoundException,
NoSuchMethodException,
InvocationTargetException {
//使用了泛型(空参构造器)
Class<BigPerson> clazz1=BigPerson.class;
BigPerson bigPerson1=clazz1.newInstance();
System.out.println(bigPerson1);
//不使用泛型(空参构造器)
Class clazz2=bigPerson1.getClass();
BigPerson bigPerson2=(BigPerson)clazz2.newInstance();
System.out.println(bigPerson2);
//调用构造器
Class clazz3=Class.forName("BigPerson");
Constructor<BigPerson> constructor1=clazz3.getDeclaredConstructor(String.class,Integer.class,String.class);
BigPerson bigPerson3=constructor1.newInstance("geng",new Integer(22),"peng");
System.out.println(bigPerson3.toString());
//调用私有构造器
ClassLoader classLoader1=ClassTest.class.getClassLoader();
Class clazz4=classLoader1.loadClass("BigPerson");
Constructor<BigPerson> constructor2=clazz4.getDeclaredConstructor(Integer.class,String.class);
constructor2.setAccessible(true);//如果是私有构造器必须使用这个
BigPerson bigPerson4 = constructor2.newInstance(new Integer(13), "lala");
System.out.println(bigPerson4);
}
}
class BigPerson{
private String name;
private Integer age;
public String description;
public BigPerson(String name, Integer age, String description) {
this.name = name;
this.age = age;
this.description = description;
}
private BigPerson( Integer age, String description) {
this.age = age;
this.description = description;
}
public BigPerson() {
System.out.println("调用了空参构造器");
}
@Override
public String toString() {
return "BigPerson{" +
"name='" + name + '\'' +
", age=" + age +
", description='" + description + '\'' +
'}';
}
private BigPerson(String name) {
this.name = name;
}
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;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
private String show(String id){
System.out.println("你的id是:"+id);
return id;
}
private void show(){
System.out.println("你的id是:"+"123");
}
}
体会一下反射的动态性:
@Test
public void test04() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
int n= new Random().nextInt(4);
System.out.println(n);
String classPath=getClassPath(n);
Class clazz=Class.forName(classPath);
//Object obj=clazz.newInstance();
Constructor constructor=clazz.getDeclaredConstructor();
constructor.setAccessible(true);
Object obj=constructor.newInstance();
System.out.println(obj);
}
private String getClassPath(int n) {
switch (n){
case 1:return "BigPerson";
case 2:return "java.util.Date";
case 3:return "java.lang.String";
case 0:return "java.lang.Object";
}
return "";
}
通过反射获取类的属性信息
import org.junit.Test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ClassTest {
@Test
public void test01(){
Class clazz=BigPerson.class;
//获取父类和子类中的public属性
Field[] fields1=clazz.getFields();
for(Field field:fields1){
System.out.println(field);
}
System.out.println();
//获取子类所有声明的属性值
Field[] fields2=clazz.getDeclaredFields();
for(Field field:fields2){
System.out.println(Modifier.toString(field.getModifiers()));//获取权限修饰符
System.out.println(field.getName());//获取属性名
System.out.println(field.getType());//获取数据类型
}
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE,ElementType.CONSTRUCTOR})
@interface MyAnnotation{
String value() default "geng";
}
class Big{
private int a;
public String b;
public Big(int a, String b) {
this.a = a;
this.b = b;
}
public Big() {
}
}
@MyAnnotation("hello")
class BigPerson extends Big{
@MyAnnotation("lala")
private String name;
private Integer age;
public String description;
public BigPerson(String name, Integer age, String description) {
this.name = name;
this.age = age;
this.description = description;
}
private BigPerson( Integer age, String description) {
this.age = age;
this.description = description;
}
public BigPerson() {
System.out.println("调用了空参构造器");
}
@Override
public String toString() {
return "BigPerson{" +
"name='" + name + '\'' +
", age=" + age +
", description='" + description + '\'' +
'}';
}
private BigPerson(String name) {
this.name = name;
}
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;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@MyAnnotation
private String show(String id){
System.out.println("你的id是:"+id);
return id;
}
private void show(){
System.out.println("你的id是:"+"123");
}
}
通过属性获取方法信息:
import org.junit.Test;
import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
public class ClassTest {
@Test
public void test01(){
Class clazz=BigPerson.class;
//获取当前类所有声明的方法
Method[] methods=clazz.getDeclaredMethods();
//获取当前类及其父类(直接父类和间接父类)的所有public方法
Method[] methods1=clazz.getMethods();
//获取当前类某个方法上面的注解
for(Method method:methods){
Annotation[] annotations=method.getAnnotations();
for(Annotation annotation:annotations){
System.out.println(annotation);
}
}
System.out.println();
//获取方法的权限修饰符
for(Method method:methods){
System.out.println(Modifier.toString(method.getModifiers()));
}
//获取方法的返回值类型
for(Method method:methods){
System.out.println(method.getReturnType());
}
//获取方法的方法名
for(Method method:methods){
System.out.println(method.getName());
}
//获取方法的形参列表
for(Method method:methods){
System.out.print(method.getName()+" :");
Parameter[] parameters=method.getParameters();
if(parameters!=null&¶meters.length!=0){
for(Parameter parameter:parameters){
//System.out.print(parameter.getName());
System.out.println(parameter.getType());
//......
}
}
System.out.println();
}
//抛出的异常
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE,ElementType.CONSTRUCTOR})
@interface MyAnnotation{
String value() default "geng";
}
class Big{
private int a;
public String b;
public Big(int a, String b) {
this.a = a;
this.b = b;
}
public Big() {
}
}
@MyAnnotation("hello")
class BigPerson extends Big{
@MyAnnotation("lala")
private String name;
private Integer age;
public String description;
public BigPerson(String name, Integer age, String description) {
this.name = name;
this.age = age;
this.description = description;
}
private BigPerson( Integer age, String description) {
this.age = age;
this.description = description;
}
public BigPerson() {
System.out.println("调用了空参构造器");
}
@Override
public String toString() {
return "BigPerson{" +
"name='" + name + '\'' +
", age=" + age +
", description='" + description + '\'' +
'}';
}
private BigPerson(String name) {
this.name = name;
}
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;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@MyAnnotation
private String show(String id){
System.out.println("你的id是:"+id);
return id;
}
private void show(){
System.out.println("你的id是:"+"123");
}
}
import org.junit.Test;
import java.lang.annotation.*;
import java.lang.reflect.*;
public class ClassTest {
@Test
public void test01() {
//获取父类的Class对象
Class clazz=BigPerson.class.getSuperclass();
System.out.println(clazz);
//获取带泛型的父类
Type type=BigPerson.class.getGenericSuperclass();
System.out.println(type);
//获取泛型参数
ParameterizedType parameterizedTypes=(ParameterizedType)type;
Type[] types=parameterizedTypes.getActualTypeArguments();
for(Type type1:types){
System.out.println(type1.getTypeName());
}
//获取运行时类实现的接口,所在包,注解等等信息
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE,ElementType.CONSTRUCTOR})
@interface MyAnnotation{
String value() default "geng";
}
class Big<T>{
private int a;
public String b;
public Big(int a, String b) {
this.a = a;
this.b = b;
}
public Big() {
}
}
@MyAnnotation("hello")
class BigPerson extends Big<String>{
@MyAnnotation("lala")
private String name;
private Integer age;
public String description;
public BigPerson(String name, Integer age, String description) {
this.name = name;
this.age = age;
this.description = description;
}
private BigPerson( Integer age, String description) {
this.age = age;
this.description = description;
}
public BigPerson() {
System.out.println("调用了空参构造器");
}
@Override
public String toString() {
return "BigPerson{" +
"name='" + name + '\'' +
", age=" + age +
", description='" + description + '\'' +
'}';
}
private BigPerson(String name) {
this.name = name;
}
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;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@MyAnnotation
private String show(String id){
System.out.println("你的id是:"+id);
return id;
}
private void show(){
System.out.println("你的id是:"+"123");
}
}
通过反射操作属性
import org.junit.Test;
import java.lang.annotation.*;
import java.lang.reflect.*;
public class ClassTest {
@Test
public void test01() throws NoSuchFieldException, IllegalAccessException, InstantiationException {
Class<BigPerson> clazz=BigPerson.class;
Field fieldName=clazz.getDeclaredField("name");
BigPerson bigPerson=clazz.newInstance();
fieldName.setAccessible(true);
fieldName.set(bigPerson,"lala");
System.out.println(bigPerson.getName());
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE,ElementType.CONSTRUCTOR})
@interface MyAnnotation{
String value() default "geng";
}
class Big<T>{
private int a;
public String b;
public Big(int a, String b) {
this.a = a;
this.b = b;
}
public Big() {
}
}
@MyAnnotation("hello")
class BigPerson extends Big<String>{
@MyAnnotation("lala")
private String name;
private Integer age;
public String description;
public BigPerson(String name, Integer age, String description) {
this.name = name;
this.age = age;
this.description = description;
}
private BigPerson( Integer age, String description) {
this.age = age;
this.description = description;
}
public BigPerson() {
System.out.println("调用了空参构造器");
}
@Override
public String toString() {
return "BigPerson{" +
"name='" + name + '\'' +
", age=" + age +
", description='" + description + '\'' +
'}';
}
private BigPerson(String name) {
this.name = name;
}
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;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@MyAnnotation
private String show(String id){
System.out.println("你的id是:"+id);
return id;
}
private void show(){
System.out.println("你的id是:"+"123");
}
}
通过反射操作方法
import org.junit.Test;
import java.lang.annotation.*;
import java.lang.reflect.*;
public class ClassTest {
@Test
public void test01() throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Class<BigPerson> clazz=BigPerson.class;
BigPerson bigPerson=clazz.newInstance();
Method methodShow1=clazz.getDeclaredMethod("show",String.class);
Method methodShow2=clazz.getDeclaredMethod("show");
methodShow1.setAccessible(true);
String result1=(String)methodShow1.invoke(bigPerson,"我是一个形参");
System.out.println(result1);
methodShow2.setAccessible(true);
String result2=(String)methodShow2.invoke(bigPerson);
System.out.println(result2);
//调用静态方法
Method methodShow3=clazz.getDeclaredMethod("lala",String.class);
methodShow3.setAccessible(true);
String result3=(String)methodShow3.invoke(BigPerson.class,"geng");
System.out.println(result3);
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE,ElementType.CONSTRUCTOR})
@interface MyAnnotation{
String value() default "geng";
}
class Big<T>{
private int a;
public String b;
public Big(int a, String b) {
this.a = a;
this.b = b;
}
public Big() {
}
}
@MyAnnotation("hello")
class BigPerson extends Big<String>{
@MyAnnotation("lala")
private String name;
private Integer age;
public String description;
public BigPerson(String name, Integer age, String description) {
this.name = name;
this.age = age;
this.description = description;
}
private BigPerson( Integer age, String description) {
this.age = age;
this.description = description;
}
public BigPerson() {
System.out.println("调用了空参构造器");
}
@Override
public String toString() {
return "BigPerson{" +
"name='" + name + '\'' +
", age=" + age +
", description='" + description + '\'' +
'}';
}
private BigPerson(String name) {
this.name = name;
}
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;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@MyAnnotation
private String show(String id){
System.out.println("你的id是:"+id);
return id;
}
private void show(){
System.out.println("你的id是:"+"123");
}
private static String lala(String s){
return "lala"+s;
}
}