Java - 反射和泛型

阅读数:193 评论数:0

跳转到新版页面

分类

python/Java

正文

1、类型信息

指程序能够在运行时发现和使用类型信息,我们一般使用两种方式来实现运行时对象和类的信息:传统的RTTI和反射机制。

(1)class对象

专门用来保存类的信息,所有类都是动态加载到JVM中的,在他们第一次使用的时候,类加载器会首先检查Class对象是否加载,如果没有,那么找到同名的class文件,然后加载字节码文件,验证代码的完整性和安全性,一旦这个类型的class对象加载到内存中,它将会用来创建所有此类的对象。
class对象的生成方式如下:

  1. Class.forName(“类名字符串”)
  2. 类名.class
  3. 实例对象.getClass()
package Refect;
class Demo{
	//other code...
}
class hello{
	public static void main(String[] args){
		Class<?> demo1 = null;
		Class<?> demo2 = null;
		Class<?> demo3 = null;
		try{
			demo1 = Class.forName("Reflect.Demo");
		}cathc(Exception e){
			e.printStackTrace();
		}
		demo2 = new Demo().getClass();
		demo3 = Demo.class;
	}
	System.out.println("类名称 "+demo1.getName());//Reflect.Demo
	System.out.println("类名称 "+demo2.getName());//Reflect.Demo
	System.out.println("类名称 "+demo3.getName());//Reflect.Demo
}

2、instanceof & isAssignableFrom

告诉我们对象是不是某个特定类型的实例。

isAssignableFrom 是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的超类或接口。

3、反射

RTTI(运行时类型信息)和反射之间真正的区别只在于,对于RTTI来说,编译器在编译时打开和检查.class文件,而对于反射机制来说,.class文件在编译时是不可获取的,所以是在运行时打开和检查.class文件。
反射主要是指程序可以访问、检测和修改它本身或行为的一种能力

package Reflect;
interface China{
	public String name = "Rollen";
	public int age = 20;
	public void sayChina();
	public void sayHello(String name,int age);
}
class Person implements China{
	private String sex;
	public Person(){};
	public Person(String sex){this.sex = sex;}
	public getSex(){return sex;}
	public setSex(String sex){this.sex = sex;}
	@Override
	public void sayChina(){
		System.out.println("hello, china");
	}
	@Override
	public void sayHello(String name,int age){
		System.out.println(name+" "+age);
	}
}
class hello{
	public static void main(String[] args){
		Class<?> demo = null;
		try{
			demo = Class.forName("Reflect.Person")
		}catch(Exception e){e.printStackTrace();}
		//保存所有的接口
		Class<?> intes[] demo.getInterfaces();
		for(int i=0;i<intes.length;++i){
			System.out.println("实现的接口 "+intes[i].getName());
			//Reflect.China
		}
		//获得全部的构造函数
		Constructor<?> cons[]= demo.getConstructors();
		for(int i=0;i<cons.length;++i){
			System.out.println("构造函数: "+cons[i]);
		}
		//通过反射调用其它类中的方法
		try{
			Method method = demo.getMethod("sayHello");
			mehtod.invoke(demo.newInstance());
		}catch(Exception e){e.printStackTrace();}
		Object obj = null;
		try{
			obj = demo.newInstance();
		}catch(Exception e){e.printStackTrace();}
		//通过反射操作属性
		Field field = demo.getDeclaredField("sex");
		field.setAccessible(true);
		field.set(obj,"男");
	}
}

(1)获取Field

可以在运行时检查类的字段(成员变量)并且get/set它们的值。

Class aClass = ...//obtain class object
Field[] methods = aClass.getFields();

一旦你获得了一个Field实例,你可以像这样通过Field.getName方法获得字段名。

Field field = ... //obtain field object
String fieldName = field.getName();


Field field = aClass.getField("someField");
Object fieldType = field.getType();

获取和设置Field的值

Class  aClass = MyObject.class
Field field = aClass.getField("someField");
MyObject objectInstance = new MyObject();
Object value = field.get(objectInstance);
field.set(objetInstance, value);

传递get和set方法的参数objectInstance必须是拥有该字段的实例。如果字段是静态字段,则传null作为get和set方法的参数。

在Java的反射使用中,如果字段是私有的, 那么必须要对这个字段设置

filed.setAccessible(true)

这样才可以正常使用,否则或报错:cannot access a member of...

4、泛型

(1)通配符

通配符的上界

? extends myClass其中“?”就是通配符,其上界为myClass,这句话代表myClass或其子类。
List<Apple> apples = new ArrayList<Apple>();
List<? extends Fruit> fruits = apples;

通配符的下界

? super myClass表示通配符的下界为myClass,这句话代表myClass的超类型直至Object。
List<Fruit> fruits = new ArrayList<Fruit>();
List<? super Apple> = fruits;

无界通配符

?等价于Object。

(2)泛型方法

之所以声明泛型方法,一般是因为你想要在该方法的多个参数之间宣称一个类型约束。

public <T> T ifThenElse(boolean b, T first, T second) {
return b ? first : second;
}

public 与返回值中间的<T>可以理解为声明此方法为泛型方法。

泛型方法的调用,在方法名前的尖括号中放具体的类型

String middle = ArrayAlg.<String>getMiddle("I'm","ixenos");

大多数情况下,方法调用可以省略<T>,编译器有足够的信息推断出调用的方法,这里利用形参数类型String[]与泛型类型T[]匹配,推断出T是String,故可以调用

String middle = ArrayAlg.getMiddle("I'm","ixenos");

(3)泛型类

在编译器,是无法知道K和V是什么类型,只有在运行时才会真正根据类型来构造和分配内存。

public class Container<K,V>{
  private K key;
  private V value;
  ....
}

(4)泛型接口

public interface Generator<T>{
  public T text();
}

 




相关推荐

obj.instanceof(class) 这个对象是不是这种类型 class.isinstance(obj) 这个对象能不能转化为这个类</p