java 反射

反射的引入

在这里插入图片描述


/*
 * 这个接口实现4个功能
 *   注册
 *   登录
 *   添加
 *   删除
 * 
 */
public interface Servlet {
	/**
	 * 服务方法
	 */
	public void service();
	
	
}



public class RegisterServlet implements Servlet {

	@Override
	public void service() {
		System.out.println("----register  service----");
	}

	public RegisterServlet() {
		System.out.println("-----RegisterServlet-------");
	}
	
	

}



public class LoginServlet implements Servlet {

	@Override
	public void service() {
		System.out.println("----login service----");
	}
	
	public LoginServlet(){
		System.out.println("-------LoginServlet--------");
	}

}


public class DeleteServlet implements Servlet {

	@Override
	public void service() {
		System.out.println("---delete  service----");
	}

	public DeleteServlet() {
		System.out.println("--------DeleteServlet--------");
	}
	
	

}



public class AddServlet implements Servlet {

	@Override
	public void service() {
		System.out.println("------add service------");
	}

	public AddServlet() {
		System.out.println("-----AddServlet---------");
	}
	
	

}
  • 功能:
    * 键盘录入数字
    * 录入1:调用注册功能(创建注册对象,调用注册方法)
    * 录入2:调用登录功能(创建登录对象,调用登录方法)
    * 录入3:调用添加功能(创建添加对象,调用添加方法)
    *
    * 问题1:使用多态代替具体的对象
    * 问题2:新需求,需要增加删除的servlet
    * java的开发原则:对扩展开放 ,对修改关闭
    * 扩展:新增加的了一个删除的servlet
    * 修改:修改了switch结构,很有可能造成其他地方受影响
    * 问题3:java源代码,修改一次,就得重新编译一次,浪费时间
    * 问题4:利用xml文件代替,原始的switch结构
    * 问题5:获取到classname的字符串,但是如何将字符串转换为类Class?
    * 如何解决了? 利用反射

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;

import cn.sxt.day0107.util.XMLUtils;

public class Test {
	 * dom4J  xml方式解析
	 * @param args
	 * @throws ClassNotFoundException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws SecurityException 
	 * @throws NoSuchMethodException 
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 */
	@SuppressWarnings("unchecked")
	public static void main(String[] args) throws Exception {
		//调用xml的方法
		Map<String, String> map = XMLUtils.paserXML("web.xml");
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入数字[1-4]");
		String num = sc.nextLine();
		String className  = map.get(num);
		Class<?> clazz = Class.forName(className);
		//创建servlet的对象
		Object obj = clazz.newInstance();
		//获取service方法
		Method method = clazz.getMethod("service");
		//调用方法
		method.invoke(obj);
		
	}
	/*public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入数字");
		int num = sc.nextInt();
		Servlet servlet =null;
		switch(num){
		   case 1:servlet = new RegisterServlet();
		   		  servlet.service();
		          break;
		   case 2:servlet = new LoginServlet();
		          servlet.service();
		          break;
		   case 4:servlet = new AddServlet();
		   		  servlet.service();
		          break;
		   case 3:servlet = new DeleteServlet();
				  servlet.service();
				  break;
		   default:System.out.println("数字只能在1-3之间");       
		}
		
		
	}*/
}

在这里插入图片描述
在这里插入图片描述

  • 1 创建学生对象
    * 2 调用吃饭方法
    *
    * 反射的引入
    * 1:当你知道对象类型的时候,可以直接创建对象,并且调用方法
    * 2:在实际开发中,很多情况下,我们的类是在xml中定义的,需要通过一定的技术(dom4j),获取到xml中类名称(全名,带包名的)
    * 3:获取到Class文件
    * 如何创建对象
    * 如何调用属性、
    * 如何调用方法
    * 反射的概念
    * 1 JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;
    * 2 对于任意一个对象,都能够调用它的任意方法和属性;
    * 3 这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
    *
    * 反射的使用场合
    * 在编译期间不知道类型信息,需要通过反射,在运行期间,创建对象,调用方法,调用属性
    * 编程语言分类
    * 静态语言 C C++
    * 声明变量的时候,必须先声明数据类型,先声明类型,再给具体的值
    * int a = 10;
    * 动态语言 JS PHP
    * 给什么具体的值,那么它的类型就是什么类型
    * var a = true;
    * a = 20;
    * 半动态半静态 JAVA (多态,反射) 编译期间确定类型,运行期间确定对象
    * People p = new People();
    * People p = new Man();
    * People p = new Women();
    * 反射的作用: 可以获取Class文件中的所有信息,包括私有的
    * 1:获取Class的属性信息
    * 2:获取Class的方法信息
    * 3:获取Class的构造器信息
  • 反射的主要组成
    * Class 表示一个类 反射的入口
    * Constructor 表示构造器类
    * Filed 表示属性类
    * Method 表示方法类
public class Demo {
		 * @param args
	 * @throws ClassNotFoundException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	public static void main(String[] args) throws Exception {
		//1:普通方案,编译期间知道类型,可以直接创建对象,调用方法
		/*Student stu = new Student();
		stu.eat();*/
		//2:反射方案,编译期间不知道类型
		Class clazz = Class.forName("cn.sxt.day0107.reflecter.Student");
		clazz.newInstance();
		
		
		
	}

}


public class Student {
	
	private String name;
	private int age;
	private String sex;
	
	public void eat(){
		System.out.println("吃饭");
	}
	
	public Student(String name, int age, String sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}
	public Student() {
		System.out.println("无参的构造器");
	}
	
	

}
  • Class:表示一个类
    * 如何获取Class
    * 1: Class.forName(“java.lang.String”); 开发常用
    * 2: 类名.class
    * 3: String s = new String(); s.getClass()
public class Demo {

	public static void main(String[] args) throws ClassNotFoundException {
		//获取String的Class
		Class clazz = Class.forName("java.lang.String");
		Class clazz2 = String.class;
		Class clazz3 = void.class;
		String s = new String();
		Class clazz4 = s.getClass();
		System.out.println(clazz2==clazz3);
		
	}

}

在这里插入图片描述
在这里插入图片描述

反射:Class类的常用方法


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

public class Demo {
	public static void main(String[] args) throws Exception {
		//1:获取Student的Class
		Class clazz = Class.forName("cn.sxt.day0107.reflect3.Student");
		//2:常用方法
		//获取public属性
		Field[] fields = clazz.getFields();
		//获取所有属性,包括私有的
		Field[] declaredFields = clazz.getDeclaredFields();
		//获取指定属性 只能获取public属性
		Field field = clazz.getField("name");
		//获取指定属性   获取所有指定的属性
		Field field2 = clazz.getDeclaredField("sex");
		
		
		//获取所有的public的方法 包括父类的公开方法
		Method[] methods = clazz.getMethods();
		//获取所有的方法,包括私有的  只能获取本类的所有方法
		Method[] declaredMethods = clazz.getDeclaredMethods();
		//获取指定的public方法
		Method m = clazz.getMethod("sleep", int.class,String.class);
		//获取所有的指定方法,包括私有的
		Method m2= clazz.getDeclaredMethod("work");
		
		
		//获取所有的public的构造器
		Constructor[]  cons = clazz.getConstructors();
		//获取所有的构造器,包括私有的
		Constructor[] cons2 = clazz.getDeclaredConstructors();
		//获取指定的public的构造器
		Constructor con = clazz.getConstructor(String.class,int.class);
		//获取指定的构造器,包括私有的
		Constructor con2 =
		 clazz.getDeclaredConstructor(String.class,int.class,String.class);
		
		
		//获得类的完整名称
		System.out.println(clazz.getName());
		//获取此类所属的包
		System.out.println(clazz.getPackage());
		//获取此类的父类
		System.out.println(clazz.getSuperclass());
		//获取此类实现的接口
		Class[] it1 = clazz.getInterfaces();
		
	}

}

public class People {
	
	public void a(){
		System.out.println("a方法");
	}

}



public class Student extends People implements Serializable,Comparable{
	
	public String name;
	private int age;
	private String sex;
	
	
	public void eat(){
		System.out.println("吃饭");
	}
	public void sleep(int a,String s){
		System.out.println("睡觉");
	}
	private void work(){
		System.out.println("工作");
	}
	
	private Student(String name, int age, String sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	
	}
	public Student() {
		System.out.println("无参的构造器");
	}
	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		return 0;
	}
	
	

}

使用反射技术创建对象

在这里插入图片描述
在这里插入图片描述

1.获取Student的Class
  • 功能:以Student类为例
    * 属性设值
    * 属性获取
    * 普通方案
    * 1 Student stu = new Student();
    * 2 stu.name = “张三”;
    * 反射方案
    * 1:获取Student的Class
    * 2:获取Student类的Constructor类
    * 3:创建Student的对象
    * 4:获取指定的属性
    * 5:通过对象给属性赋值
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class Demo {
	public static void main(String[] args) throws Exception {
		//1  获取Student的Class
		Class<?> clazz = Class.forName("cn.sxt.day0107.reflect4.Student");
		//2 获取Student类的Constructor类
		Constructor<?> con = clazz.getConstructor();
	    //3  使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,
	    并用指定的初始化参数初始化该实例。 newInstance()
		Object stu = con.newInstance();
		//4:获取指定的public属性
		Field name = clazz.getField("name");
		//5:通过对象给属性赋值
		name.set(stu, "张三");
		//6:获取属性的值
		System.out.println(name.get(stu));
		
		System.out.println("------------------");
		
		//5:获取私有的属性
		Field  age = clazz.getDeclaredField("age");
		//6:解除私有化,暴力破解
		age.setAccessible(true);
		//6:给age赋值
		age.set(stu, 20);
		//7:获取age的值
		System.out.println(age.get(stu));
		
	}

}


public class People {
	
	public void a(){
		System.out.println("a方法");
	}

}

import java.io.Serializable;

public class Student extends People implements Serializable,Comparable{
	
	public String name;
	private int age;
	private String sex;
	
	
	public void eat(){
		System.out.println("吃饭");
	}
	public void sleep(int a,String s){
		System.out.println("睡觉");
	}
	private void work(){
		System.out.println("工作");
	}
	
	private Student(String name, int age, String sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	
	}
	public Student() {
		System.out.println("无参的构造器");
	}
	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		return 0;
	}
	
	

}

获取Student类的Constructor类
  • Constructor 类的用法
  • 1:获取Student的Class *
    2:创建对象 *
    2.1   直接通过Class.newInstance();
        只能调用无参的构造函数 *
    2.2  先获取Constructor,再通过Constructor,
        调用newInstance(Class… args) *
    注意:如果要调用有参的构造器,必须先获取Constructor
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class Demo {
   	public static void main(String[] args) throws Exception {
				//1:获取Student的Class
		Class<?> clazz = Class.forName("cn.sxt.day0107.reflect5.Student");
		//2:可以直接通过Class调用无参的构造器
		//clazz.newInstance();
		//2:获取无参的构造器
		//Constructor<?> con = clazz.getConstructor();
		//3:获取1个参数的构造器   传的是形参的类型
		/*Constructor<?> con = clazz.getConstructor(String.class);
		//4:创建对象   传的是实参的值
		Object obj = con.newInstance("张三");
		//5:获取name的Field
		Field field = clazz.getField("name");
		//6:给name属性赋值
		 field.set(obj, "李四");
		//7:获取name的属性值
		System.out.println(field.get(obj));*/
		
		System.out.println("--------------------");
		//获取2个参数的构造器
		/*Constructor<?> con2 = clazz.getConstructor(String.class,int.class);
		//给name和age初始话
		Object obj2 = con2.newInstance("张三",20);
		//获取name和age的Field属性
		Field name = clazz.getField("name");
		Field age = clazz.getDeclaredField("age");
		
		//设置age的访问权限
		age.setAccessible(true);
		
		//获取name和age值
		System.out.println(name.get(obj2));
		System.out.println(age.get(obj2));*/
		
		System.out.println("--------------------");
		//1:获取3 个参数的构造器
		Constructor<?> con = 
		clazz.getDeclaredConstructor(String.class,int.class,String.class);
		//2:设置构造器的访问权限
		con.setAccessible(true);
		//3:创建对象 属性初始化
		Object obj = con.newInstance("张三",20,"男");
		//4:获取name,age,sex的Field
		Field name = clazz.getField("name");
		Field age = clazz.getDeclaredField("age");
		Field sex = clazz.getDeclaredField("sex");
		//5:设置age和sex的访问权限
		age.setAccessible(true);
		sex.setAccessible(true);
		//6:获取name,age,sex的属性值
		System.out.println(name.get(obj));
		System.out.println(age.get(obj));
		System.out.println(sex.get(obj));
		//普通方案
		Student stu = new Student("张三", 20, "男");
	   
}
   
}
Constructor的常用方法

public class Demo2 {
	 //  以String为例
	public static void main(String[] args) throws Exception {
		
		//1:获取Object的Class
		Class<?> clazz = Class.forName("java.lang.String");
		//2:获取String的所有构造器
		/*Constructor<?>[] con = clazz.getDeclaredConstructors();
		//3:遍历构造器
		for (Constructor<?> c : con) {
			System.out.println(c);
		}*/
		//4:获取指定的构造器
		Constructor<?> con = clazz.getConstructor(byte[].class,String.class);
		System.out.println(con);
		//5:获取构造函数的修饰符
		System.out.println(Modifier.toString(con.getModifiers()));
		//6 获取构造函数的名称
		System.out.println(con.getName());
		//7 获取构造函数的形参
		Class<?>[] ty = con.getParameterTypes();
		for (Class<?> c1 : ty) {
			System.out.println(c1.getTypeName());
		}
		//8 获取构造器的异常
		Class<?>[] et = con.getExceptionTypes();
		System.out.println(et[0].getName());
		//5:创建String对象
		//Object obj = con.newInstance(new byte[]{97,98,99},"UTF-8");
		//System.out.println(obj);
		
		
		
	}

}
public class Student{
	
	public static transient String name;
	private int age;
	private String sex;
	
	
	public void eat(){
		System.out.println("吃饭");
	}
	public void sleep(int a,String s){
		System.out.println("睡觉");
	}
	private void work(){
		System.out.println("工作");
	}
	
	public Student(String name, int age, String sex) {
		this.name = name;
		this.age = age;
		this.sex = sex;
		System.out.println("3个参数的构造器");
	}
	public Student(String name, int age) {
		this.name = name;
		this.age = age;
		System.out.println("2个参数的构造器");
	
	}
	public Student(String name) {
		this.name = name;
		System.out.println("1个参数的构造器");
	
	}
	public Student() {
		System.out.println("无参的构造器");
	}
	
	

}

在这里插入图片描述

public class Demo {
	
	/*
	 * Method 的用法
	 *  以Student为例
	 *  1:创建Student的Class
	 *    Class<?> clazz = Class.forName("cn.sxt.day0107.reflect6.Student");
	 *  2:获取Student的无参构造器
	 *    Object obj = clazz.newInstance();
	 *  3:获取指定的public方法  eat
	 *    Method method = clazz.getMethod("eat");
	 *  4:通过对象调用方法
	 *    method.invoke(obj);
	 *    
	 * 普通方案
	 *   1:创建Student对象
	 *     Student stu = new Student();
	 *   2:调用方法
	 *     stu.eat();  
	 * 
	 */
	public static void main(String[] args) throws Exception {
		//1:创建Student的Class
		Class<?> clazz = Class.forName("cn.sxt.day0107.reflect6.Student");
		//2:获取Student的无参构造器
		Object obj = clazz.newInstance();
		//3:获取指定的public方法  eat
		/*Method method = clazz.getMethod("eat");
		//4:通过对象调用方法
		method.invoke(obj);*/
		
		//1:创建无参无返回值的Method
		  Method method = clazz.getMethod("show1");
		  System.out.println(method.invoke(obj));
		//2:创建无参有返回值的Method
		  Method method1 = clazz.getMethod("show2");
		  System.out.println(method1.invoke(obj));
		//3:创建有参无返回值的Method
		  Method method2 = clazz.getMethod("show3",int.class);
		  System.out.println(method2.invoke(obj, 100));
		//4:创建有参有返回值的Method
		  Method method3 = clazz.getMethod("show4",String.class);
		  System.out.println(method3.invoke(obj, "你好"));
		
	}

}


public class Demo2 {
	
	/*
	 * Method调用实体类的set和get方法
	 * 
	 */
	public static void main(String[] args) throws Exception {
		
		Class<?> clazz = Class.forName("cn.sxt.day0107.reflect6.Student");
		Object obj = clazz.newInstance();
		
		String s = "set";
		String s1 = "get";
		String name = "name";
		//属性的首字母转为大写
		String ss = name.substring(0, 1).toUpperCase()+name.substring(1);
		//获取setName的Method
		Method method = clazz.getMethod(s+ss, String.class);
		//调用方法
		method.invoke(obj, "张三");
		//获取getName的Method
		Method method1 = clazz.getMethod(s1+ss);
		//调用方法
		System.out.println(method1.invoke(obj));
	}

}



public class Demo3 {
	
	/*
	 * Method的常用方法
	 *  以String类型
	 * 
	 */
	public static void main(String[] args) throws Exception {
	
		Class<?> clazz = Class.forName("java.lang.String");
		Object obj = clazz.newInstance();
		//获取String的所有方法
		/*Method[] method = clazz.getDeclaredMethods();
		//遍历
		for (Method m : method) {
			System.out.println(m);
		}*/
		//获取String的指定方法
		Method method = clazz.getMethod("getBytes", String.class);
		//获取方法的修饰符
		System.out.print(Modifier.toString(method.getModifiers())+"  ");
		//获取方法的返回值
		System.out.print(method.getReturnType().getTypeName()+"  ");
		//获取方法的名称
		System.out.print(method.getName()+"(");
		//获取方法的形参
		System.out.print(method.getParameters()[0].getType().getName()+")  ");
		//获取方法的异常
		System.out.println("throws "+method.getExceptionTypes()[0].getName());
		
		System.out.println(method);
	}

}



public class Student{
	
	public static transient String name;
	private int age;
	private String sex;
				public static String getName() {
		return name;
	}
	public static void setName(String name) {
		Student.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public void eat(){
		System.out.println("吃饭");
	}
	public void sleep(int a){
		System.out.println("睡觉");
	}
	
	public void show1(){
	  System.out.println("无参无返回值");
	}
	
	public int show2(){
		 System.out.println("无参有返回值");
		return 10;
	}
	public void show3(int a){
		 System.out.println("有参无返回值");
		
	}
	public String show4(String s){
		 System.out.println("有参有返回值");
		 return s;
		
	}
	private void work(){
		System.out.println("工作");
	}
	
	public Student(String name, int age, String sex) {
		this.name = name;
		this.age = age;
		this.sex = sex;
		System.out.println("3个参数的构造器");
	}
	public Student(String name, int age) {
		this.name = name;
		this.age = age;
		System.out.println("2个参数的构造器");
	
	}
	public Student(String name) {
		this.name = name;
		System.out.println("1个参数的构造器");
	
	}
	public Student() {
		System.out.println("无参的构造器");
	}
	
	

}
利用反射突破泛型的限制

public class Demo {
		public static void main(String[] args) throws Exception {
		ArrayList<String> al = new ArrayList<>();
		al.add("a");
		al.add("b");
		al.add("c");
		
		//使用反射突破泛型限制
		Class<? extends ArrayList> clazz = al.getClass();
		//获取add的Method  参数类型是Object类型
		Method method = clazz.getMethod("add", Object.class);
		//调用方法
		method.invoke(al, 100);
		method.invoke(al, 100.123F);
		method.invoke(al, true);
		
		System.out.println(al);
		
	}
	

}

在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值