11.
一点一点的来
Class类中有一个forName(String className)方法,向方法中传入包中完整的类名,当然要是字符串类型的,说过反射是运行期的行为,在编译的时候编译器当然只会认为你传入的只是字符串而已;由于返回类名,所以生成一个Class类型的实例来接收
12.
对于一个Class类来说里面的方法是值得深究的,是因为有一个类,它的名字就是Class,不要搞混了,Class类中有一个方法,
Methdo[] getDeclareMethods(),即返回一个Method类型的数组,那么Method又是怎样的呢:他是一个定义在reflect下的一个类,它有自己的toString方法,就是打印出当前所指的方法名:
加上数组之后就是要打印出目标类中的所有方法,
来看一下下面的程序:
package com.jianjian2;
import java.lang.reflect.Method;
public class ReflectTest
{
public static void main(String[]args)throws Exception
{
Class <?>classType = Class.forName("java.lang.String");
Method[] method = classType.getDeclaredMethods();
for(Method meth : method)
{
System.out.println(meth);
}
}
}
13.
反射的第一步永远是获得要操作类的对象。然后是方法。
14.
关于泛型中的模糊继承,我们常常会见到
T extends superClass 的语句,为什要采用这种方式呢?其实只定义T 意义是不大的,我们常常会用不确定的类,但是想调用确定的方法,在泛型中我们可以采用继承父类或者接口来实现这种设想
比如说,我想定义一个类型,我希望里面有一个 compareTo()方法,而我们知道compareTo方法是接口 Comparable 中的,子类有很多,所以我们可以这样限制 ArrayList<T extends Compareble> 这样就可以往动态数组中添加实现了compareble的类型了,而且可以使用里面定义的方法。
看一下例子:
package com.jianjian2.Reflection;
public class GeniericTest6
{
public static void main(String[] args)
{
People<String> people = new People<String>("a","n");
String[] s = {"a","b","vc"};
people.method(s);
}
}
class People<TextendsComparable>
{
private T s1;
private T s2;
public People(T s1, T s2)
{
this.s1 = s1;
this.s2 = s2;
}
public T getS1()
{
return s1;
}
public void setS1(T s1)
{
this.s1 = s1;
}
public T getS2()
{
return s2;
}
public void setS2(T s2)
{
this.s2 = s2;
}
public void method(T[] t)
{
for(inti= 0;i < t.length;i ++)
{
System.out.println(t[i].compareTo(t[i]));
}
}
}
15.
Java里的对象是不能直接拿来用的,我们只能使用指向对象的实例来操作类:
在反射中我们除了要生成类对象之外,别忘了还要生成对象的实例;
反射生成的对象,想当于Class 它的作用就是使用里面的方法,但是类里面具体定义的方法只能使用实例来调用。
总之感觉反射是一步一步的来的:
看下面的程序:
/*
*在一个类中定义一个方法,利用反射来调用这个方法
* 首先要用到类,肯定要生成类的对象,要用到类中的方法,肯定要生成对象的实例、
* 想要调用对象的方法,肯定要生成方法对象(Object):其实反射中位于Java.lang.reflect包下的类其实只是为我们提供了指示
* 我们需要自己定义object来接受那些类提供的信息
*
*/
package com.jianjian7;
import java.lang.reflect.Method;
public class InstanceOfTest
{
public static void main(String[]args)throws Exception
{
Class<?>c = Student.class;//生成一个Student对象;
Objectinstance = c.newInstance();//生成对象的实例;
MethodaddMethod = c.getMethod("method1",new Class[] {int.class,int.class});
System.out.println(addMethod);
//打印这个方法的话,会打印出方法的详细名称,路径加上方法名
//public int com.jianjian7.Student.method1(int,int)
//调用Class类中此方法,目的是要确定调用那一个方法参数一表示方法的字符串名,后面的可变参数表示有参数类型所构成的Class类型的数组;
//防止方法重载;
Object result= addMethod.invoke(instance,new Object[]{1,2});//生成一个方法对象指向指定的方法
//参数一是对象实例,后面的是为方法添加参数对象的数组;
System.out.println((Integer)result);//打印方法会直接调用方法,这点是值得注意的;
}
}
class Student
{
public int method1 (int i,int j)
{
System.out.println( i + j);
return i + j;
}
}
16.
反射中获得类的对象的方式有几种,注意总结
17.
抽象方法充当着占位的作用。
18.‘
巩固一下泛型 典型的运用:
package com.jianjian2.Generic;
public class GenericTest
{
public static void main(String[] args)
{
Person<String, Integer > s = new Person<String, Integer >();
String s1 = "zhangsan";
int s2 = 6;
s.setName(s1);
s.setAge(s2);
System.out.println(s.getName());
System.out.println(s.getAge());
}
}
class Person <T,K>
{
private T name;
private K age;
public T getName()
{
return name;
}
public void setName(T name)
{
this.name = name;
}
public K getAge()
{
return age;
}
public void setAge(K age)
{
this.age = age;
}
}
19.
可是要理解好这句话的意思啊:
获取某个类或某个对象的所对应的Class对象的三种方式:
a) 使用Class类的静态方法forName(“具体类名”);
b) 使用类 的.class语法:String.class;
c) 使用对象的getClass()方法:String s = “a”;Class <?>
C = s.getClass 记住喽是获得Class对象!
19.
Class 提供的getMethod方法是用来调用对象的方法,其中有一个 newInstance() 方法是新生成实例,也是新生成了构造方法,但是这个构造方法只能是不带参数的构造方法,如果向往构造参数里面传入参数的话就要使用别的方式了
:要想生成带参数的构造方法,需要调用位于java.lang.reflection下的Constructor类的newInstance()方法,里面要接收参数,还有就是 方法会返回一个 Countructor类型的数据,要调用这个数据还必须通过Class类的getCountructor方法。
意思就是我得到了 Countructor 对象,还要找到一个接受它的实例;
20.
感觉就是反射调用方法,构造方法,类名,在方式上是大同小异的,具体来说
第一步: 首先获得目标类的Class对象,具体三种方法
第二步: 假设调用构造方法(通用),首先通过Class对象来调用你要使用什么,方法还是构造方法还是域,这里当然选择构造方法,Class返回来的都是一个梗概对象,reflection下还有接应Class返回的梗概,同一标识为 Object
若想通过类的不带参数的构造方法来生成对象,我们有两种方式:
a)先获得Class对象,然后通过该Class对象的newInstance()方法直接生成即可:
Class<?>classType = String.class;
Objectobj = classType.newInstance();
b)先获得Class对象,然后通过该对象获得对应的Constructor对象,再通过该Constructor对象的newInstance()方法生成:
Class<?>classType = Customer.class;
Constructorcons = classType.getConstructor(new Class[]{});
Objectobj = cons.newInstance(new Object[]{});
4.若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式:
Class<?>classType = Customer.class;
Constructorcons = classType.getConstructor(new Class[]{String.class, int.class});
Objectobj = cons.newInstance(new Object[]{“hello”, 3});
5.Integer.TYPE返回的是int,而Integer.class返回的是Integer类所对应的Class对象。
21.
看下列程序 描述分别利用三种方法调用Person的Class对象
package com.jianjian2.Reflection;
public class ReflectionTest3
{
public static void main(String[] args )throws Exception
{
Class<?> c1 = Person.class;
Personperson = new Person();
Class<?> c2 = person.getClass();
Class<?> c3 = Class.forName("com.jianjian2.Reflection.Person");
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
}
}
class Person
{
public Person()
{
System.out.println("xi wang nixing fu ...");
}
public Person(String i,int j)
{
System.out.println(i);
System.out.println(j);
}
}
看打印结果
:class com.jianjian2.Reflection.Person
classcom.jianjian2.Reflection.Person
class com.jianjian2.Reflection.Person
显然是相同的!
22.
具体演示调用 通用构造方法(即 可以接收带和不带参数的构造方法)
:
package com.jianjian2.Reflection;
import java.lang.reflect.Constructor;
public class ReflectionTest3
{
public static void main(String[] args )throws Exception
{
Class<?> c1 = Person.class;
Person person = new Person();
Class<?> c2 = person.getClass();
Class<?> c3 = Class.forName("com.jianjian2.Reflection.Person");
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
Constructor con = c1.getConstructor(new Class[]{String.class,int.class});
//与调用Method不同的是不用使用字符串指定大体是那个方法名,因为构造函数由参数类型数量区分;
Object obj = con.newInstance(newObject[]{"wohenxiangni",36});
System.out.println(obj);
//我们还可以这样写只需要一步:
//Object obj =c1.getConstructor(new Class[] {String.class,int.class}).newInstance(newObject[] {“wohenxiangni”, 36});
}
}
class Person
{
public Person()
{
System.out.println("xi wang nixing fu ...");
}
public Person(String i,int j)
{
System.out.println(i);
System.out.println(j);
}
}
有几点是要说明一下的
1. 构造方法在生成的时候即已经被调用了;所以程序红色部分就算没有前半部分一样调用构造方法打印 I j;
2. 最后打印Obj 肯定是调用父类 toString方法,所以别指望打印出 I j ;
打印结果:
xi wang ni xing fu ...
classcom.jianjian2.Reflection.Person
classcom.jianjian2.Reflection.Person
classcom.jianjian2.Reflection.Person
wohenxiangni