Java学习笔记十

时间:2023-02-25 15:52:02


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