java-----RTTI与反射

java在运行时动态识别对象和类信息的方式有两种:

(1)传统的RTTI(Run-Time Type Identification),他假定我们编译时已经知道了所有类型;

(2)反射机制,允许我们在运行时发现和使用类的信息;

RTTI运行时类型标识主要表现在三个方面:

(1)Class对象: 每个类都有一个Class对象,便以一个新类都会产生Class对象;

(2)强制类型转换:

    Parent parent = new Child( );

    Child child = (Child)parent;

(3)instanceof关键字用于检查对象是不是属于特定类型;

多态是基于RTTI实现的,其功能主要由Class类实现,Class类是"类的类",如果说类是对象的抽象和集合的话,那么Class类就是对类的抽象和集合,正是由于Class对象的存在,java不会因为类型的向上转型而迷失,这就是多态的原理;

RTTI与反射最大的区别在于:

RTTI在编译时需要知道最重要的东西---类名,而反射在编译期不需要做任何事情,匿名对象信息只有在运行时获取到即可以啦;

下面用多个例子来学习java反射:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class JavaReflect {
	/**
	 * 获取一个类的包名、类名
	 */
	public static void test1()
	{
		Employee employee = new Employee();
		System.out.println("完整包名:  "+employee.getClass().getPackage());
		System.out.println("包含包名的类名1:  "+employee.getClass().getName());
		System.out.println("包含包名的类名2:  "+employee.getClass().getCanonicalName());
		System.out.println("简单类名1:  "+employee.getClass().getSimpleName());
	}
	/**
	 * 反射生成实例并且设置实例的属性值
	 * 通过获得无参构造器生成实例
	 * 通过public有参构造器生成实例
	 * 通过private有参构造器生成实例
	 */
	public static void test2()
	{
		try {
			Class clazz = Class.forName("com.hzw.day33.Employee");
			Employee employee = (Employee) clazz.newInstance();//反射生成实例,这里需要Employee对象必须具有无参构造器
			employee.setAge(24);
			System.out.println("采用无参构造器设置age:  "+employee.getAge());
			Constructor[] constructors = clazz.getConstructors();
			System.out.println("所有的public类型构造器为:  ");
			for(Constructor constructor :constructors)
			{
				System.out.println(constructor.getName());
			}
			Constructor[] constructors2 = clazz.getDeclaredConstructors();
			System.out.println("所有构造器(包括public和private的类型)");
			for(Constructor constructor:constructors2)
			{
				System.out.println(constructor.getName());
			}
			try {
				Constructor constructor3 = clazz.getDeclaredConstructor(String.class,int.class);
				Employee employee2 = (Employee) constructor3.newInstance("hzw",20);
				System.out.println("采用public有参构造器设置age值: "+employee2.age);
				Constructor constructor4 = clazz.getDeclaredConstructor(String.class);
				constructor4.setAccessible(true);//设置私有构造器为可以访问
				Employee employee3 = (Employee) constructor4.newInstance("huzhiwei");
				System.out.println("采用private有参构造器设置name值:  "+employee3.name);
			} catch (Exception e) {
				e.printStackTrace();
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 通过反射操作成员变量
	 */
	public static void test3()
	{
		try {
			Class clazz = Class.forName("com.hzw.day33.Employee");
			Employee employee = (Employee) clazz.newInstance();
			Field field = clazz.getDeclaredField("name");
			field.setAccessible(true);
			field.set(employee, "huzhiwei");
			System.out.println("通过反射生成设置employee的name属性为:  "+employee.getName());
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	/**
	 * 通过反射获取到父类以及接口
	 */
	public static void test4()
	{
		try {
			Class clazz = Class.forName("com.hzw.day33.Employee");
			System.out.println("父类是:  "+clazz.getSuperclass());
			Class[] interfaces = clazz.getInterfaces();
			System.out.println("所有接口为:  ");
			for(Class c:interfaces)
			{
				System.out.println(c);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * 通过反射获取所有类方法(包括私有的)并且调用类方法
	 */
	public static void test5()
	{
		try {
			Class clazz = Class.forName("com.hzw.day33.Employee");
			Method[] methods = clazz.getDeclaredMethods();//获取到所有的method
			System.out.println("获取到的所有method方法如下:  ");
			for(Method method:methods)
			{
				System.out.println("函数方法名:  "+method.getName()+"   函数返回类型:  "+method.getReturnType()+"   函数访问修饰符"+Modifier.toString(method.getModifiers())+"   函数本身:  "+method);
			}
			//反射调用函数
			Method method1 = clazz.getDeclaredMethod("print");
			method1.setAccessible(true);//需要设置print函数是可访问的
			System.out.println("反射调用无参函数:  ");
			method1.invoke(clazz.newInstance(),null);//还有一种写法:method1.invoke(clazz.newInstance());
			System.out.println("反射调用有参函数:  ");
			Method method2 = clazz.getDeclaredMethod("printName",String.class);
			method2.setAccessible(true);
			method2.invoke(clazz.newInstance(), "山西");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * 通过反射获得类加载器
	 */
	public static void test6()
	{
		try {
			Class clazz = Class.forName("com.hzw.day33.Employee");
			System.out.println("类加载器为:  "+clazz.getClassLoader());
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	public static void main(String[] args) {
		System.out.println("test1");
		test1();
		System.out.println("---------------------------------------");
		System.out.println("test2");
		test2();
		System.out.println("---------------------------------------");
		System.out.println("test3");
		test3();
		System.out.println("---------------------------------------");
		System.out.println("test4");
		test4();
		System.out.println("---------------------------------------");
		System.out.println("test5");
		test5();
		System.out.println("---------------------------------------");
		System.out.println("test6");
		test6();
		System.out.println("---------------------------------------");
	}
}
class Employee extends Manager implements DoSomething,CompleteSomething
{
	public String name;
	public int age;
	public Employee() {
	}
	private Employee(String name)
	{
		this.name = name;
	}
	public Employee(String name,int age) {
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public int changeAge()
	{
		age = age+1;
		return age;
	}
	private void print()
	{
		System.out.println("正在调用print方法");
	}
	public void printName(String name)
	{
		System.out.println("调用printName输出名字为:  "+name);
	}
}
class Manager
{
	
}
interface DoSomething
{
	
}
interface CompleteSomething
{
	
}
/*
输出:
test1
完整包名:  package com.hzw.day33
包含包名的类名1:  com.hzw.day33.Employee
包含包名的类名2:  com.hzw.day33.Employee
简单类名1:  Employee
---------------------------------------
test2
采用无参构造器设置age:  24
所有的public类型构造器为:  
com.hzw.day33.Employee
com.hzw.day33.Employee
所有构造器(包括public和private的类型)
com.hzw.day33.Employee
com.hzw.day33.Employee
com.hzw.day33.Employee
采用public有参构造器设置age值: 20
采用private有参构造器设置name值:  huzhiwei
---------------------------------------
test3
通过反射生成设置employee的name属性为:  huzhiwei
---------------------------------------
test4
父类是:  class com.hzw.day33.Manager
所有接口为:  
interface com.hzw.day33.DoSomething
interface com.hzw.day33.CompleteSomething
---------------------------------------
test5
获取到的所有method方法如下:  
函数方法名:  getName   函数返回类型:  class java.lang.String   函数访问修饰符public   函数本身:  public java.lang.String com.hzw.day33.Employee.getName()
函数方法名:  setName   函数返回类型:  void   函数访问修饰符public   函数本身:  public void com.hzw.day33.Employee.setName(java.lang.String)
函数方法名:  print   函数返回类型:  void   函数访问修饰符private   函数本身:  private void com.hzw.day33.Employee.print()
函数方法名:  setAge   函数返回类型:  void   函数访问修饰符public   函数本身:  public void com.hzw.day33.Employee.setAge(int)
函数方法名:  getAge   函数返回类型:  int   函数访问修饰符public   函数本身:  public int com.hzw.day33.Employee.getAge()
函数方法名:  printName   函数返回类型:  void   函数访问修饰符public   函数本身:  public void com.hzw.day33.Employee.printName(java.lang.String)
函数方法名:  changeAge   函数返回类型:  int   函数访问修饰符public   函数本身:  public int com.hzw.day33.Employee.changeAge()
反射调用无参函数:  
正在调用print方法
反射调用有参函数:  
调用printName输出名字为:  山西
---------------------------------------
test6
类加载器为:  sun.misc.Launcher$AppClassLoader@6c68bcef
---------------------------------------
*/
注意点:

(1)getConstructors与getDeclaredConstructor的区别: 

    getConstructors得到的是所有public类型的构造函数,getDeclaredConstructor得到的是所有构造函数,包括public、private等等类型的;

(2)setAccessible(true)的用途:设置某个private类型的函数可以访问;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值