Java学习反射之基础

今天小编学习了Java里比较核心的反射原理,明白了反射是Java非常突出的一个动态相关机制。

解释一下,反射机制是Java在运行状态中,对于于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制,很多优秀的开源框架都是通过反射完成的。理解了反射,就是成为大神的第一步!

public class Simple {
public static void main(String[] args) {
Simple s=new Simple();
System.out.println(s.getName());
}
}

以上是一般人常用创建类对象实例化的方法,然后可以随意调用类中的一切方法。

然而在反射机制中,可以实现以下功能:

  1. 在运行时判断任意一个对象所属的类;
  2. 在运行时构造任意一个类的对象;
  3. 在运行时判断任意一个类所具有的成员变量和方法;
  4. 在运行时调用任意一个对象的方法;
  5. 生成动态代理;

获取源头Class(重点)

所有类的对象其实都是Class的实例。这个 Class 实例可以理解为类的模子,就是包含了类的结构信息,类似于图纸。我们日常生活中,需要创造一个产品,如想山寨一个iphone手机,怎么办?

有三种方式可以实现:

⑴买个iphone手机,拆的七零八落的,开始山寨;

⑵到iphone工厂参观,拿到iphone磨具,开始山寨;

⑶跑到美国盗取iphone的图纸,开始山寨,最后一种最暴力,最爽。

同理,获取类的Class对象也有三种方式

⑴Class.forName(”包名.类名”) //一般尽量采用该形式

(2)类.class

(3)对象.getClass()

获取Class对象

Class是一切的源头,所有伟大的事业都有一个不起眼的开头。而反射有三种出场方式:

第一种:对象.class

Source s=new Source();
Class<?>c1=s.getClass();
System.out.println(c1.getName());

第二种:类.class

Class<?>c2=Source.class;
System.out.println(c2.getName());

前两种看看就行,第三种最强最暴力

Class<?> c3=Class.forName("com.myclass.Source");
System.out.println(c3.getName());

有了class对象,我们就有了一切,这就是反射的源头,接下来就是“庖丁解牛”。

获取修饰符

获取修饰符,使用 getModifiers() 即可,通过此方法可以获得整形数字,与修饰符一一对应, Modifier 类提供了 static 方法和常量来解码类和成员访问修饰符。

Class<?>clz=Class.forName("com.myClass.User");
//获得修饰符
int n=clz.getModifiers();
//使用Modifier转换为相应的字符串
System.out.println(Modifier.toString(n)

创建对象

根据Class对象,我们可以获得构造器,为实例化对象做准备。调用相应方法:

public class GetConstructor {
public static void main(String[] args) {
try {
Class<?>clz=Class.forName("com.myclass.User");
//1、获取所有的public 权限的构造器
Constructor<?>[]con=clz.getConstructors();
//注意查看构造器的顺序
for(Constructor<?> c:con){
System.out.println(c);
}
//2、获取所有的构造器
con=clz.getDeclaredConstructors();
System.out.println("--------------");
for(Constructor<?> c:con){
System.out.println(c);
}
System.out.println("----------------");
//3、获取指定的构造器(放入具体的类型)
Constructor<?> c=clz.getConstructor(String.class);
System.out.println(c);
//非public权限
System.out.println("----------------");
c=clz.getDeclaredConstructor(String.class,String.class);
System.out.println(c);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

实例化对象(重点)

创建对象的方式,有new 、克隆、反序列化,再加一种,根据Class对象,使用 newInstance() 或者构造器实例化对象。调用以下 newInstance() 即可。

Class<?> clz = Class.forName("com.myClass.User");
//第一种:通过newInstance()创建对象
User user=(User)clz.newInstance();
user.setUname("sad");
user.setUpwd("good");
//第二种:通过getDeclaredConstructors()创建对象,取得全部构造函数(注意顺序)
Constructor<?>[] cons=clz.getDeclaredConstructors();
for(Constructor<?>c:cons){
System.out.println(c);
}
//注意观察上面的输出结果,再实例化,否则参数容易出错
User u1=(User)cons[0].newInstance("sad","good");
User u2=(User)cons[1].newInstance("sad");
User u3=(User)cons[2].newInstance();
System.out.println(u1.getUname()+u1.getUpwd());

注意: newInstance() 是调用空构造,如果空构造不存在,会出现异常。由此可知,使用其他构造器创建对象比较麻烦,使用空构造非常简单。确保自定义类的空构造存在。

父类与接口

我们还可以通过方法获取父类或者父类接口

Class<?> clz =Class.forName("com.myClass.User");
//获取所有接口
Class<?>[] inters=clz.getInterfaces();
for(Class<?> in:inters){
System.out.println(in.getName());
}
//获取父类
Class<?> cls=clz.getSuperclass();
System.out.println("继承的父类为:"+cls.getName());

属性和方法

同样的我们可以通过相应的方法来获取类中的属性和方法,包括父类和接口中的。

属性

获取所有属性(包括父类或接口) ,使用 Field 即可操作, Field 作为描述属性的对象。

Class<?> clz = Class.forName("com.myClass.User");
//获取属性
System.out.println("===============本类属性==========");
// 取得本类的全部属性
Field[] field = clz.getDeclaredFields();
for (int i = 0; i < field.length; i++) {
// 1、权限修饰符
int mo = field[i].getModifiers();
String vis = Modifier.toString(mo);
// 2、属性类型
Class<?> type = field[i].getType();
//3、名字
String name = field[i].getName();
System.out.println(vis + " " + type.getName() + " "+ name + ";");
}
System.out.println("=========公开的属性包括接口或者父类属性======");
field = clz.getFields();
for (int i = 0; i < field.length; i++) {
System.out.println(field [i]);
}

数组

反射类不仅能操作类,也能操作数组。

//1、创建数组
Object obj =Array.newInstance(int.class, 5);
//2、获取大小
if(obj.getClass().isArray()){ //3、判断是否为数组
System.out.println(Array.getLength(obj));
//4、设置值
Array.set(obj,0, 100);
//5、获取值
System.out.println(Array.get(obj,0));
}

总结:在我看来,类是对对象的描述,有属性,有方法,而反射让我觉得这是一个对类的类,描述了类的名字,权限,成员属性,成员方法。了解反射可以进一步了解Java的底层!

莫等闲,白了少年头,空悲切。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值