无论是Java开发还是Android开发,反射的使用必不可少。反射可以通过类名或类对象获取一系列的类方法,类成员,基类以及类实现接口。总而言之,只要知道类名或类对象,类中的一切信息就显得透明化。
那反射有什么作用呢?可以从以下几个方面来阐述其作用。
1.解决Android编译期问题。
Android开发中难免有些需求是要求进行基于系统源码开发的,但此时有些类或方法已经被系统封装开发者没有权限获取,那怎么解决呢,通过反射开发者就能绕过系统权限,获取对应的所需类信息。
2.针对Android的热修复
在一个需求多变的环境中,需求不可能一次性就想得非常透彻。有时软件已经发出发现有问题,需要及时修复。此时开发者就可以通过反射进行相应类中Bug修复,这为软件的热修复提供了便利。当然脚本软件的原理也是如此。
3.绕过安全限制开发
在开发中,难免会遇到基于源码开发。但不是源码中的所有类开发者都是可以调用。例如Android开发中,自定义对话框,安装程序等。其中的这些都是系统封装好的,开发者没有权限操作。这种情况只能通过反射绕过Android系统限制进行二次开发,这样对Android系统有更深的理解和更高的控制权。
好了费话不多说,下面详细介绍下java反射的使用。
(一)Class类对象的获取
ImageUtils imageUtils = new ImageUtils();
//第一种形式获得类对象
Class c1 = ImageUtils.class;
//第二种形式获取类对象
Class c2 = imageUtils.getClass();
//第三种形式获得类对象(其中forname中参数必须是含包名的类名全称)
Class c3 = Class.forName("com.example.ImageUtils");
//获取全称类名(带包名)
System.out.println("className = "+ c1.getName());
//获取类名(不带包名)
System.out.println("class:"+c1.getSimpleName());
System.out.println("className = "+ c2.getName());
System.out.println("className = "+ c3.getName());
主要有以上三种方式获取Class对象,以方便后期使用。其运行结果如下。
(二)某个类中的一些方法的获取
ImageUtils imageUtils = new ImageUtils();
Class c = imageUtils.getClass();
//获得ImgeUtils中所有非public以及public方法
Method mtd[] = c.getDeclaredMethods();
//获取ImageUtils中的所有public方法
Method methods[] = c.getMethods();
//获取某个类中的某个方法(如:获取参数为int型的setI方法)
Method m1 = c.getMethod("setI",new Class[]{int.class});
Method m2 = c.getDeclaredMethod("setI",new Class[]{int.class});
//获取某个类的构造方法
Constructor obj1[] = c.getConstructors();
Constructor obj2[] = c.getDeclaredConstructors();
//获取某个带参数的构造方法
Constructor obj3 = c.getConstructor(new Class[]{int.class});
Constructor obj4 = c.getDeclaredConstructor(new Class[]{int.class});
//获取基础类的一些信息
Class cls = c.getSuperclass();
//获取对应基础类中的方法
Method base[] = cls.getDeclaredMethods();
for (int i=0;i
通过上面的操作获取类中对应的所有方法或声明过的方法以及继承的基础类和接口中的方法。其具体的运行结果如下。
(三)获取类中某个方法的返回值以及参数类型
ImageUtils imageUtils = new ImageUtils();
Class c = imageUtils.getClass();
//获得ImgeUtils中所有public方法
Method mtd[] = c.getDeclaredMethods();
for (int i = 0;i < mtd.length;i++){
Class paramestype[] = mtd[i].getParameterTypes();
Class returntype = mtd[i].getReturnType();
System.out.println("returntype = "+ returntype.getName());
for (int j = 0;j < paramestype.length;j++){
System.out.println("paramestype = "+ paramestype[j].getName());
}
}
通过上面的操作可查看对应方法的参数以及返回值类型,没有返回值则返回void。其运行结果如下。
(四)某个类中的成员变量的获取
ImageUtils imageUtils = new ImageUtils();
Class c = imageUtils.getClass();
Field[] fields = c.getFields();
for (int i=0;i
通过上面的操作可获取对应的成员变量以及成员变量的类型。其运行结果如下。
(五)通过反射设置某个成员变量的值
ImageUtils imageUtils = new ImageUtils();
Class c3 = Class.forName("com.example.ImageUtils");
Method m = c3.getDeclaredMethod("setI",new Class[]{int.class});
m.invoke(imageUtils,new Object[]{100});
Method getMethod = c3.getDeclaredMethod("getI");
System.out.println("i: "+ getMethod.invoke(imageUtils));
(注意:这里操作的ImageUtils对象必须同一个否者获取不到正确修改后的值,如使用m.invoke(c3.newInstance(),newObject[]{100})和getMethod.invoke(c3.newInstance())这样就获取不到i修改后的值,因为c3.newinstance()方法表示新建了一个对象,换句话说在这个对象中修改了i值,在另一个新建的对象中怎么会获取到i修改后的值)。
好了java的反射的使用介绍到此结束。正式附上源码,以供有兴趣者研究与建议。
1.基类(Utils)
package com.example;
/**
* Created by jamy on 2017/3/24.
*/
public class Utils {
public void print(){
}
public void Stop(){
}
}
2.实现的接口(FaceImage)
package com.example;
/**
* Created by jamy on 2017/3/24.
*/
public interface FaceImage {
void ImagePrint();
}
3.测试类(ImageUtils)
package com.example;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import javax.imageio.ImageIO;
/**
* Created by jinfangmei on 2017/3/24.
*/
public class ImageUtils extends Utils implements FaceImage{
public int i=2;
public String Start = null;
private String name = null;
protected String password = null;
private int m = 0;
public static void ImgYin(String s,String ImgName){
byte[] bytes = null;
try{
String str = s;
File _file = new File(ImgName);
Image src = ImageIO.read(_file);
int wideth=src.getWidth(null);
int height=src.getHeight(null);
BufferedImage image=new BufferedImage(wideth,height,BufferedImage.TYPE_INT_RGB);
Graphics g=image.createGraphics();
g.drawImage(src,0,0,wideth,height,null);
g.setColor(Color.RED);
g.setFont(new Font("宋体",Font.PLAIN,20));
Font aa=new Font("宋体",Font.PLAIN,20);
g.drawString(str,wideth-150,height-10);
g.dispose();
ByteArrayOutputStream out1 = new ByteArrayOutputStream();
saveImage(image, out1);
bytes = out1.toByteArray();
out1.close();
FileOutputStream out2 = new FileOutputStream(ImgName);
out2.write(bytes);
out2.close();
}
catch(Exception e){
System.out.println(e);
}
}
public static void saveImage(BufferedImage img, OutputStream out1) throws Exception {
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out1);
encoder.encode(img);
}
@Override
public void ImagePrint() {
}
private void getName(){
}
public int getI() {
return i;
}
public void setI(int i) {
System.out.print("ImagUtils i: "+i+"\n");
this.i = i;
}
public ImageUtils(){
}
public ImageUtils(int m){
this.m = m;
}
}
4.主类(TestImageCollect)
package com.example;
public class TestImageCollect {
public int i=0;
public String Start=null;
private String end = null;
public static void main(String[] args) {
try {
// ImageUtils imageUtils = new ImageUtils();
// //第一种形式获得类对象
// Class c1 = ImageUtils.class;
// //第二种形式获取类对象
// Class c2 = imageUtils.getClass();
// //第三种形式获得类对象(其中forname中参数必须是含包名的类名全称)
// Class c3 = Class.forName("com.example.ImageUtils");
// //获取全称类名(带包名)
// System.out.println("className = "+ c1.getName());
// //获取类名(不带包名)
// System.out.println("class:"+c1.getSimpleName());
// System.out.println("className = "+ c2.getName());
// System.out.println("className = "+ c3.getName());
/*****************获取Class类中的一些方法***********************************************/
// ImageUtils imageUtils = new ImageUtils();
// Class c = imageUtils.getClass();
// //获得ImgeUtils中所有非public以及public方法
// Method mtd[] = c.getDeclaredMethods();
// //获取ImageUtils中的所有public方法
// Method methods[] = c.getMethods();
// //获取某个类中的某个方法(如:获取参数为int型的setI方法)
// Method m1 = c.getMethod("setI",new Class[]{int.class});
// Method m2 = c.getDeclaredMethod("setI",new Class[]{int.class});
// //获取某个类的构造方法
// Constructor obj1[] = c.getConstructors();
// Constructor obj2[] = c.getDeclaredConstructors();
// //获取某个带参数的构造方法
// Constructor obj3 = c.getConstructor(new Class[]{int.class});
// Constructor obj4 = c.getDeclaredConstructor(new Class[]{int.class});
// //获取基础类的一些信息
// Class cls = c.getSuperclass();
// //获取对应基础类中的方法
// Method base[] = cls.getDeclaredMethods();
// for (int i=0;i