反射及其应用
反射
通过java反射机制,程序员可以更加深入的控制程序的运行过程,还可以逆向控制程序的执行过程;而这种功能是通过访问对象类构造函数、方法、成员实现的。
1、Class类
Class类描述java程序中的各个java类;Class类的实例是字节码
Class类对象的获取方式:
类名.class ; 如:Student.class
类对象.getClass(); 如:stu.getClass();
Class.forName(); 如: Class.forName("java.lang.String ");
1、Constructor 类:访问构造函数
方法:
- getConstructors();
获得所有权限为public的构造方法
- gerConstructors(Class<>...... parameterTypes);
获得权限为public的指定构造方法
- getDeclaredConstructors();
获得所有构造方法,按声明顺序返回;
- getDeclaredConstructors(Class<>....... parameterTypes);
获得指定构造方法
例:
ObjectClass。getDeclaredCOnstructor(String.class , int.class);
Constructor类中一个非常重要的方法:
newInstance(object initargs);
通过该构造方法创建一个指定类型的该类对象,如果没设置参数这表示采用默认无参数的构造方法;
2、Filed类:访问成员变量
(给方法功能与Constructor相似)
- getFileds();
- getField(String name);
- getDeclaredFileds();
- getDeclaredFiled(String name);
Filed类中一个非常很重要的方法:
setAccessible(boolean b);
该方法可以设置是否忽略权限为private等私有权限的成员变量;为true是,允许使用该成员变量,即便其权限为private;
3、Method类:访问方法
- getMethods();
- getMethods(String name, Class<> ...... parameter);
- getDeclaredMethods();
- getDeclaredMethods(String name, Class<>...... parameter);
Method常用类中已给重要方法:
invoke(Object obj, Object ...... args);
l利用指定参数执行指定对象obj中的该方法,返回值为Object类型
该方法在逆向控制中,非常实用。
4、反射应用
需求:利用反射实现扩展数组长度
1 package unit16; 2 3 import java.lang.reflect.*; 4 5 public class ReFlexTest2 { 6 7 public static void main(String[] args) { 8 9 Test test = new Test(); 10 11 test.print(); 12 13 test.is = (int[]) addArrayLength(test.is, 10); 14 test.ss = (String[]) addArrayLength(test.ss, 10); 15 16 test.print(); 17 18 } 19 20 public static Object addArrayLength(Object array, int newLength) { 21 Object newArray = null; 22 Class componentType = array.getClass().getComponentType();//创建反射对象 23 newArray = Array.newInstance(componentType, newLength);//使用指定参数创建一个该类对象 24 System.arraycopy(array, 0, newArray, 0, Array.getLength(array));//通过替换,生成新数组 25 return newArray; 26 } 27 } 28 29 class Test { 30 31 public int[] is = { 1, 2, 3 }; 32 33 public String[] ss = { "A", "B", "C" }; 34 35 public void print() {//遍历数组 36 37 for (int index = 0; index < is.length; index++) { 38 System.out.println("is[" + index + "]=" + is[index]); 39 } 40 41 System.out.println(); 42 43 for (int index = 0; index < ss.length; index++) { 44 System.out.println("ss[" + index + "]=" + ss[index]); 45 } 46 47 System.out.println(); 48 49 } 50 51 }
例2: 使用反射初步验证用户输入信息
1 /* 2 * 通过反射初步验证用户输入信息 3 */ 4 5 package unit16; 6 7 import java.awt.*; 8 import java.awt.event.*; 9 import java.lang.reflect.*; 10 11 import javax.swing.*; 12 13 public class ReFlexTest extends JFrame{ 14 private JTextField textField_2; 15 16 private JTextField textField_1; 17 18 private JTextField textField; 19 20 /** 21 * Launch the application 22 * 23 * @param args 24 */ 25 public static void main(String args[]) { 26 try { 27 ReFlexTest frame = new ReFlexTest(); 28 frame.setVisible(true); 29 } catch (Exception e) { 30 e.printStackTrace(); 31 } 32 } 33 34 /** 35 * Create the frame 36 */ 37 public ReFlexTest() { 38 super(); 39 setBounds(100, 100, 500, 375); 40 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 41 42 final JPanel panel = new JPanel(); 43 panel.setLayout(new GridBagLayout()); 44 getContentPane().add(panel, BorderLayout.CENTER); 45 //定义姓名文本框 46 final JLabel label = new JLabel(); 47 label.setText("姓名:"); 48 final GridBagConstraints gridBagConstraints = new GridBagConstraints(); 49 gridBagConstraints.gridy = 0; 50 gridBagConstraints.gridx = 0; 51 panel.add(label, gridBagConstraints); 52 textField = new JTextField(); 53 textField.setName("姓名"); 54 textField.setColumns(20); 55 final GridBagConstraints gridBagConstraints_5 = new GridBagConstraints(); 56 gridBagConstraints_5.gridy = 0; 57 gridBagConstraints_5.gridx = 1; 58 panel.add(textField, gridBagConstraints_5); 59 //定义性别单选按钮 60 final JLabel label_1 = new JLabel(); 61 label_1.setText("性别:"); 62 final GridBagConstraints gridBagConstraints_1 = new GridBagConstraints(); 63 gridBagConstraints_1.gridy = 1; 64 gridBagConstraints_1.gridx = 0; 65 panel.add(label_1, gridBagConstraints_1); 66 final JPanel panel_1 = new JPanel(); 67 final GridBagConstraints gridBagConstraints_4 = new GridBagConstraints(); 68 gridBagConstraints_4.gridy = 1; 69 gridBagConstraints_4.gridx = 1; 70 panel.add(panel_1, gridBagConstraints_4); 71 72 final JRadioButton radioButton = new JRadioButton(); 73 radioButton.setText("男"); 74 panel_1.add(radioButton); 75 76 final JRadioButton radioButton_1 = new JRadioButton(); 77 radioButton_1.setText("女"); 78 panel_1.add(radioButton_1); 79 80 //定义出生日期文本框 81 final JLabel label_2 = new JLabel(); 82 label_2.setText("出生日期:"); 83 final GridBagConstraints gridBagConstraints_2 = new GridBagConstraints(); 84 gridBagConstraints_2.gridy = 2; 85 gridBagConstraints_2.gridx = 0; 86 panel.add(label_2, gridBagConstraints_2); 87 textField_1 = new JTextField(); 88 textField_1.setName("出生日期"); 89 textField_1.setColumns(20); 90 final GridBagConstraints gridBagConstraints_6 = new GridBagConstraints(); 91 gridBagConstraints_6.gridy = 2; 92 gridBagConstraints_6.gridx = 1; 93 panel.add(textField_1, gridBagConstraints_6); 94 95 //定义身份证文本框 96 final JLabel label_3 = new JLabel(); 97 label_3.setText("身份证号:"); 98 final GridBagConstraints gridBagConstraints_3 = new GridBagConstraints(); 99 gridBagConstraints_3.gridy = 3; 100 gridBagConstraints_3.gridx = 0; 101 panel.add(label_3, gridBagConstraints_3); 102 textField_2 = new JTextField(); 103 textField_2.setName("身份证号"); 104 textField_2.setColumns(20); 105 final GridBagConstraints gridBagConstraints_7 = new GridBagConstraints(); 106 gridBagConstraints_7.gridy = 3; 107 gridBagConstraints_7.gridx = 1; 108 panel.add(textField_2, gridBagConstraints_7); 109 110 //定义确定按钮,并添加监听器 111 final JButton button = new JButton(); 112 button.setText("确定"); 113 button.addActionListener(new ActionListener() { 114 public void actionPerformed(ActionEvent e) { 115 // 通过Java反射机制获得类中的所有属性 116 Field[] fields = ReFlexTest.class.getDeclaredFields(); 117 for (int i = 0; i < fields.length; i++) { 118 Field field = fields[i]; 119 if (field.getType().equals(JTextField.class)) { // 只验证JTextField类型的属性 120 field.setAccessible(true); // 默认情况下不允许访问私有属性,如果设为true则允许访问 121 JTextField textField = null; 122 try { 123 textField = (JTextField) field.get(ReFlexTest.this); // 获得本类中的对应属性 124 } catch (Exception ex) { 125 ex.printStackTrace(); 126 } 127 if (textField.getText().trim().length() == 0) { // 查看该属性是否为空 128 String info = "请填写“" + textField.getName() 129 + "”!"; 130 JOptionPane.showMessageDialog(null, info, 131 "友情提示", 132 JOptionPane.INFORMATION_MESSAGE); 133 textField.requestFocus(); // 令为空的文本框获得焦点 134 return; 135 } 136 } 137 } 138 139 } 140 }); 141 final GridBagConstraints gridBagConstraints_8 = new GridBagConstraints(); 142 gridBagConstraints_8.gridy = 4; 143 gridBagConstraints_8.gridx = 1; 144 panel.add(button, gridBagConstraints_8); 145 // 146 } 147 148 }
总结: “反射就是把java类中的各种成分映射成相应的java类”,反射虽然可以逆向控制程序的执行,但这种方式会导致程序运行时间变长,效率降低。
所以在使用反射方法时,要考虑到这对程序运行效率的影响。