您的位置:首页 > 编程语言 > Java开发

Java反射reflect学习笔记_3:反射类的方法

2015-11-17 16:15 453 查看
今天给大家po出我的第三份关于学习反射的笔记,关于对类的方法的反射。其中包括静态方法,普通方法,带参数的方法,以及最重要的String[]数组的方法的反射以及需要注意的细节问题,都是基础,所以请各位多多包涵!

有关前面两篇文章请看下面:

Java反射reflect学习笔记_1:反射的简述

Java反射reflect学习笔记_2:反射类的构造函数

//===================================================

// 反射类的方法

//===================================================

本文由机智猫亲手写,转载请尊重版权:/article/11906586.html

| 首先,通过Class获取类的字节码

|Class clazz = Class.forName("com.marer.reflect.Person");

|

| 1.反射无参的方法: public void aa1()

|Method method = clazz.getMethod("aa", null);

|第一个参数:方法名;第二个参数:方法的参数,若为无参方法可以为null值

|

|执行方法:

|method.invoke(p, null);//第一个参数:你要调用哪个对象的方法,假设new了一个新的对象p;第二个参数:被反射的对象的方法所需要的参数,如果无参数则传null

|

|

|

| 2.反射带一个或者多个参数的方法: public void aa(String name, int age)

|Method method = clazz.getMethod("aa", String.class, int.class);//第一个参数:方法名;第二个参数:可变参数,根据你所需要调用方法的约定进行调用

|第一个参数:方法名;第二个参数:可变参数,根据你所需要调用方法的约定进行调用

|

|执行方法:

|method.invoke(p, "老张,成功了", 23);//第一个参数:你要调用哪个对象的方法,假设new了一个新的对象p;第二个参数:可变参数

|

|

|

| 3.反射带数组的方法,并返回Class数组: public Class[] aa(String name, int[] ages)

|Method method = clazz.getMethod("aa", String.class, int[].class);//在这里,原方法第二个参数中是个int数组,那么就传int[].class

|

|执行方法:

|Class cs[] = (Class[]) method.invoke(p, "老李,成功了", new int[]{1,2,3});

|

|

|

| 4.反射类的私有方法: private void aa(InputStream in)

|Method method = clazz.getDeclaredMethod("aa", InputStream.class);//private方法用getDeclaredMethod()

|method.setAccessible(true);//打开访问权限,暴力反射

|

|执行方法:

|Class cs[] = (Class[]) method.invoke(p, new FileInputStream("D:\\我的文档\\Q.txt"));

|

|

|

| 5.反射类的静态方法: public static void aa(int num)

|Method method = clazz.getMethod("aa", int.class);

|

|执行方法:

|method.invoke(123);//静态方法调用不需要对象,直接执行

|与普通方法不同,在静态方法中,因为静态方法是一直存在的,因此不需要通过对象的访问进行调用,只需要直接调用

|而需要通过对象调用的普通方法,执行的是对象内部的方法,对其他的对象没有影响

|

|

|

| 6.反射类的main方法,以及有且只有一个参数并且参数类型为数组的方法的反射、特殊的参数String[] 的反射方法:

|public static void main(String[] args)

|public static boolean doDelete(int[] ids)

|

|反射:

|Method method = clazz.getMethod("main", String[].class);//这里指定方法名为main,指定参数为String[]数组

|

|执行方法一:

|method.invoke(null, new Object[]{new String[]{"123","weq"}});//第一种方法,将String[]数组参数包装在数组中,到了invoke()里面就会对应拆分出一个String数组

|

|执行方法二:

|method.invoke(null, (Object) new String[]{"123","weq"});//第二种方法,推荐使用,将参数的数组包装在一个Object中,并且由JDK拆分,拆分出第一个参数就是数组,那么就会通过调用

|//注意:这里将String[]数组参数封装为(Object)对象是允许的因为Object对象是所有对象的始祖

|

|

|注意:1.上面的main方法的反射以及调用,适用所有的有且只有一个String[]数组为参数的方法,对于其他类型的数组可以不用包装,例如只有一个int[]参数的方法

|method.invoke(null, new int[]{1,2});//如果只有一个int[]数组为参数的反射,可以不用像上面那样封装,即使封了也没问题invoke(null, (Object)new int[]{1,2})

|

|

|注意:2.对于String和包装类(例如:Integer,Charater..),如果一个或多个参数都是同样的(String或包装类),就可以通过new 数组的形式进行invoke反射调用,例如:

|1.一个或多个String参数,必须都是String,如果有一个参数不一样(例如String和String[]数组都是不一样的,那么就不能够通过下面的方法进行反射调用方法

|类方法:public static void test(String s1, String s2)

|反射方法:Method method = clazz.getMethod("test", String.class, String.class);

|反射方法的invoke调用:method.invoke(null, new String[]{"asd","123"});

|//当然,上面的也可以通过普通的两个个字符串参数进行invoke调用

|

|

|

|2.一个或多个包装类的方法都是一样的:(Integer,Character...)

|类方法:public static void test6(Integer a1, Integer a2)

|反射方法:Method method = clazz.getMethod("test6", Integer.class,Integer.class);

|反射方法的invoke调用:method.invoke(null, new Integer[]{1,2});

|//必须注意:两个基础数据类型的int不能通过数组进行invoke反射调用,乖乖地一个个传参吧

|//Method method = clazz.getMethod("test4", int.class,int.class);

|//method.invoke(null, 1,2);

|

|3.但是对于两个或以上的String[]数组声明的方法就不可以用一个数组进行invoke调用

|类方法:public static void test8(String[] s1, String[] s2)

|反射方法:Method method = clazz.getMethod("test8", String[].class, String[].class);

|反射方法的invoke调用:method.invoke(null, new String[]{"abc","def"});//这时候是抛出参数要求长度不一的异常的

|//运行结果是抛异常的,因此证明是不能通过这种方法去进行invoke调用

|

|

|4.普通类也不能通过数组的方式进行invoke调用

|类方法:public static void test7(Person p1, Person p2)

|反射方法:Method method = clazz.getMethod("test7", Person.class,Person.class);

|反射方法的invoke调用:method.invoke(null, new Person(),new Person());//两个非String或非包装类就不能用数组来invoke反射调用

|

|本文由机智猫亲手写,转载请尊重版权:/article/11906586.html

|

|总结:通过上述几个样例,大家应该可以看到反射方法的invoke调用的不同的形式

| 其实只要注意有且只有一个String[]数组作为参数的方法的反射以及调用注意的问题就可以了【直接将String[]数组的参数强转成Object即可】

|除了多个String参数或多个包装类型的方法(都必须都是String类型的参数或包装类型)可以通过在invoke的时候传一个String[]数组参数以外

|其他方法都是必须按照参数的要求对号入座

|PS.一般情况为了避免造成不必要的麻烦,都建议按照参数的个数要求进行对号入座

|

本文由机智猫亲手写,转载请尊重版权:/article/11906586.html

关于之前写的Person类:

package com.marer.reflect;

import java.io.InputStream;
import java.util.List;

public class Person {
public String str = "aa";
int a = 1233;
private int num = 4564564;
private static int num2 = 9527;
private int nums;
private String name;

public Person(){
System.out.println("person");
}

public Person(String name){
System.out.println("person name:" + name);
}

public Person(String name, int age){
System.out.println("person name:" + name + "\tage:" + age);
}

private Person(List list){
System.out.println("list");
}

//方法

public void aa(){
System.out.println("aa");
}

public void aa(String name, int age){
System.out.println("person name:" + name + "\tage:" + age);
}

public Class[] aa(String name, int[] ages){
System.out.println("有返回值的");
return new Class[]{String.class};
}

private void aa(InputStream in){
System.out.println(in);
}

public static void aa(int num){
System.out.println(num);
}

public static void main(String[] args){
System.out.println("main方法运行");
}

public static void test(String[] args){
System.out.println("字符串数组参数方法调用成功");
}

public static void test(String s1, String s2){
System.out.println("两个字符串");
System.out.println(s1);
System.out.println(s2);
}

public static void test_1(String s1, String s2,String s3){
System.out.println("三个字符串");
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
}

public static void test2(int[] a1, int[] a2){
System.out.println("两个参数为数组的方法");
System.out.println(a1.length);
for(int a: a1){
System.out.print(a+",");
}
System.out.println("\n"+a2.length);
for(int a: a2){
System.out.print(a+",");
}
}

public static void test3(int[] a1, int a2){
System.out.println("第一个参数为数组,第二个参数为普通类型的方法");
System.out.println(a1.length);
for(int a: a1){
System.out.print(a+",");
}
System.out.println(a2);
}

public static void test4(int a1, int a2){
System.out.println("两个参数为普通类型int,用数组进行invoke");
System.out.println(a1);
System.out.println(a2);
}

public static void test5(int[] a1){
System.out.println("int 数组");
for(int a:a1){
System.out.println(a);
}
}

public static void test6(Integer a1, Integer a2){
System.out.println("两个参数为普通类型Integer,用数组进行invoke");
System.out.println(a1);
System.out.println(a2);
}

public static void test7(Person p1, Person p2){
System.out.println("两个参数为普通类型Integer,用数组进行invoke");
System.out.println(p1);
System.out.println(p2);
}

public static void test8(String[] s1, String[] s2){
System.out.println("两个字符串数组");
System.out.println(s1.toString());
System.out.println(s2.toString());
}

public int getNum() {
return num;
}

public void setNum(int num) {
this.num = num;
}

public static int getNum2() {
return num2;
}

public static void setNum2(int num2) {
Person.num2 = num2;
}

public int getNums() {
return nums;
}

public void setNums(int nums) {
this.nums = nums;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}


本文由机智猫亲手写,转载请尊重版权:/article/11906586.html

这次本文的Demo类:

package com.marer.reflect;

import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;

import org.junit.Test;

//反射类的方法
public class Demo3 {

//反射类的方法:public void aa1()
@Test
public void test1() throws Exception{

Person p = new Person();

Class clazz = Class.forName("com.marer.reflect.Person");
Method method = clazz.getMethod("aa", null);//第一个参数:方法名;第二个参数:方法参数

method.invoke(p, null);//第一个参数:你要调用哪个对象的方法;第二个参数:被反射的对象的方法所需要的参数

}

//反射类的方法:public void aa(String name, int age)
@Test
public void test2() throws Exception{

Person p = new Person();

Class clazz = Class.forName("com.marer.reflect.Person");
Method method = clazz.getMethod("aa", String.class, int.class);//第一个参数:方法名;第二个参数:可变参数,根据你所需要调用方法的约定进行调用

method.invoke(p, "老张,成功了", 23);//第一个参数:你要调用哪个对象的方法;第二个参数:可变参数

}

//反射类的方法:public Class[] aa(String name, int[] ages)
@Test
public void test3() throws Exception{

Person p = new Person();

Class clazz = Class.forName("com.marer.reflect.Person");
Method method = clazz.getMethod("aa", String.class, int[].class);//在这里,原方法第二个参数中是个int数组,那么就传int[].class

Class cs[] = (Class[]) method.invoke(p, "老李,成功了", new int[]{1,2,3});

System.out.println(cs[0]);
}

//反射类的私有方法:private void aa(InputStream in)
@Test
public void test4() throws Exception{

Person p = new Person();

Class clazz = Class.forName("com.marer.reflect.Person");
Method method = clazz.getDeclaredMethod("aa", InputStream.class);//private方法用getDeclaredMethod()

method.setAccessible(true);//打开访问权限,暴力反射

Class cs[] = (Class[]) method.invoke(p, new FileInputStream("D:\\我的文档\\Q.txt"));
}

//反射类的静态方法:public static void aa(int num)
@Test
public void test5() throws Exception{
Class clazz = Class.forName("com.marer.reflect.Person");
Method method = clazz.getMethod("aa", int.class);
method.invoke(123);//静态方法调用不需要对象
}

//反射类的方法:public static void main(String[] args)
@Test
public void test6() throws Exception{
Class clazz = Class.forName("com.marer.reflect.Person");
Method method = clazz.getMethod("main", String[].class);//这里指定方法名为main,指定参数为String[]数组

//		method.invoke(null, new Object[]{new String[]{"123","weq"}});//第一种方法,将String[]数组参数包装在数组中,到了invoke()里面就会对应拆分出一个String数组
method.invoke(null, (Object) new String[]{"123","weq"});//第二种方法,推荐使用,将参数的数组包装在一个Object中,并且由JDK拆分,拆分出第一个参数就是数组,那么就会通过调用

//main方法的反射获取和调用
}

//反射类方法:public static void test(String[] args)
@Test
public void test7() throws Exception{
Class clazz = Class.forName("com.marer.reflect.Person");
Method method = clazz.getMethod("test", String[].class);

method.invoke(null, (Object) new String[]{"asd","123"});

}

//反射类方法:public static void test(String s1, String s2)
@Test
public void test8() throws Exception{
Class clazz = Class.forName("com.marer.reflect.Person");
Method method = clazz.getMethod("test", String.class, String.class);

method.invoke(null, new String[]{"asd","123"});

}

//反射类方法:public static void test_1(String s1, String s2, String s3)
@Test
public void test8_1() throws Exception{
Class clazz = Class.forName("com.marer.reflect.Person");
Method method = clazz.getMethod("test_1", String.class, String.class,String.class);

method.invoke(null, new String[]{"asd","123","456"});

}

//反射类方法:public static void test2(int[] a1, int[] a2)
@Test
public void test9() throws Exception{
Class clazz = Class.forName("com.marer.reflect.Person");
Method method = clazz.getMethod("test2", int[].class,int[].class);

method.invoke(null, new int[]{1,2,3},new int[]{4,5,6});
}

//反射类方法:public static void test3(int[] a1, int a2)
@Test
public void test10() throws Exception{
Class clazz = Class.forName("com.marer.reflect.Person");
Method method = clazz.getMethod("test3", int[].class,int.class);

method.invoke(null, new int[]{1,2,3},4);
}

//反射类方法:public static void test4(int a1, int a2)
@Test
public void test11() throws Exception{
Class clazz = Class.forName("com.marer.reflect.Person");
Method method = clazz.getMethod("test4", int.class,int.class);

method.invoke(null, 1,2);//两个基础数据类型的int不能通过数组进行invoke反射调用,乖乖地一个个传参吧
}

//反射类方法:public static void test5(int[] a1)
@Test
public void test12() throws Exception{
Class clazz = Class.forName("com.marer.reflect.Person");
Method method = clazz.getMethod("test5", int[].class);

method.invoke(null, new int[]{1,2});
}

//反射类方法:public static void test6(Integer a1, Integer a2)
@Test
public void test13() throws Exception{
Class clazz = Class.forName("com.marer.reflect.Person");
Method method = clazz.getMethod("test6", Integer.class,Integer.class);

method.invoke(null, new Integer[]{1,2});//两个基础数据类型的int不能通过数组进行invoke反射调用
}

//反射类方法:public static void test7(Person p1, Person p2)
@Test
public void test14() throws Exception{
Class clazz = Class.forName("com.marer.reflect.Person");
Method method = clazz.getMethod("test7", Person.class,Person.class);

method.invoke(null, new Person(),new Person());//两个非String或非包装类就不能用数组来invoke反射调用
}

//反射类方法:public static void test8(String[] s1, String[] s2)
@Test
public void test15() throws Exception{
Class clazz = Class.forName("com.marer.reflect.Person");
Method method = clazz.getMethod("test8", String[].class, String[].class);
method.invoke(null, new String[]{"abc","def"});//运行结果是抛异常的
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: