【面试】反射相关-这一篇全了解
什么是Java的反射机制?
答:反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有属性和方法。
Java中的反射有什么作用?
解:
在运行时判断任意一个对象所属的类。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时任意调用一个对象的方法
在运行时构造任意一个类的对象
反射有哪些优缺点?
解:
优点
反射提高了程序的灵活性和扩展性。
缺点
代码可读性低及可维护性
反射代码执行的性能低
破坏了封装性。
在业务代码中应该尽量避免使用反射。但是,作为一个合格的Java开发,也要能读懂中间件、框架中的反射代码。在有些场景下,要知道可以使用反射解决部分问题。
反射常见的用法有哪些。或者你在框架中哪些地方见过反射的使用?
解:
动态代理
JDBC的class.forName
BeanUtils中属性值得拷贝
RPC框架
ORM框架
Spring的IOC/DI
什么是Java中的Class类,他和反射有什么关系?
解:
Java的Class类是java反射机制的基础,通过Class类我们可以获得关于一个类的相关信息
Java.lang.Class是一个比较特殊的类,它用于封装被装入到JVM中的类(包括类和接口)的信息。当一个类或接口被装入的JVM时便会产生一个与之关联的java.lang.Class对象,可以通过这个Class对象对被装入类的详细信息进行访问。
虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类(型)都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。
获取“某一个类”所对应的“Class对象”有哪几种方法?
解:
1.根据对象的引用.getClass()方法获取:MyObject object=new MyObject(); Class c=object.getClass();
2.根据类名.class获取:Class c=MyObject.class;
3.根据Class中的静态方法Class.forName(); Class c=Class.forName("MyObject");
Java中创建对象的方法有几种?
解:
一、使用new关键字
这是我们最常见的也是最简单的创建对象的方式,通过这种方式我们还可以调用任意的构造函数(无参的和有参的)。
例如:
User user = new User();
二、使用反射机制
运用反射手段,调用Java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。
1 使用Class类的newInstance方法
可以使用Class类的newInstance方法创建对象。这个newInstance方法调用无参的构造函数创建对象。
//创建方法1
User user = (User)Class.forName("根路径.User").newInstance();
//创建方法2(用这个最好)
User user = User.class.newInstance();
2 使用Constructor类的newInstance方法
和Class类的newInstance方法很像, java.lang.reflect.Constructor类里也有一个newInstance方法可以创建对象。我们可以通过这个newInstance方法调用有参数的和私有的构造函数。
Constructor<User> constructor = User.class.getConstructor();
User user = constructor.newInstance();
这两种newInstance方法就是大家所说的反射。事实上Class的newInstance方法内部调用Constructor的newInstance方法。
三、使用clone方法
无论何时我们调用一个对象的clone方法,jvm就会创建一个新的对象,将前面对象的内容全部拷贝进去。用clone方法创建对象并不会调用任何构造函数。
要使用clone方法,我们需要先实现Cloneable接口并实现其定义的clone方法。
public class CloneTest implements Cloneable{
private String name;
private int 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;
}
public CloneTest(String name, int age) {
super();
this.name = name;
this.age = age;
}
public static void main(String[] args) {
try {
CloneTest cloneTest = new CloneTest("wangql",18);
CloneTest copyClone = (CloneTest) cloneTest.clone();
System.out.println("newclone:"+cloneTest.getName());
System.out.println("copyClone:"+copyClone.getName());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
四、使用反序列化
当我们序列化和反序列化一个对象,jvm会给我们创建一个单独的对象。在反序列化时,jvm创建对象并不会调用任何构造函数。
为了反序列化一个对象,我们需要让我们的类实现Serializable接口。
学习文章:Java对象的序列化与反序列化
对象的序列化和反序列化涉及的东西比较多,等补充后再总结。
实现功能:在泛型为Integer的ArrayList中存放一个String类型的对象。
public void test() throws Exception {
ArrayList<Integer> list = new ArrayList<Integer>();
Method method = list.getClass().getMethod("add", Object.class);
method.invoke(list, "Java反射机制实例");
System.out.println(list.get(0));
}
上一篇: java设计模式-工厂模式(2)