【知了堂学习笔记】JAVA反射及注解--轻松学会反射

java的反射

反射是java的重要机制,java语言的动态性与它有着莫大的关系。
通过反射可以获得获得类、属性、构造方法、方法、注解的信息
也可以利用反射机制动态操作这些内容,可以调用构造函数、操作属性、调用方法

用反射操作类中内容的步骤:
1.获取Class对象
2.得到对应实例
3.操作实例

注:Class:该对象并不是class,它是一个类的原模板,储存了类的所有信息,一维数组和二维数组不是同一个类,对象创建自动加载Class类。
同一类对象创建的模板是一致的,都是它所属类的模板。

获取Class的方法有(返回对象是Class):
1.类名.class
2.对象名.getclass()
3.Class.forName(path) --> path是java类所属路径
举个例子:

/**
 * 演示说明Class
 * @author Administrator
 *
 */
public class Test {
	public static void main(String[] args) throws ClassNotFoundException {
		Class cls=Class.forName("com.zlt.test1.Test");//用Class.forName获取Class
		System.out.println("打印Class的名字: "+cls.getSimpleName());
		String a = "aaa";
		String b = "bbb";
		System.out.println("同一类创建对象的Class: " + a.getClass()+" "+b.getClass());
		String aa[]= {};
		String bb[][]= {};
		System.out.println("一维数组和二维的Class: "+ aa.getClass() +"   "+ bb.getClass());
		System.out.println("String的Class"+String.class);
	}
}

运行结果:
在这里插入图片描述

用反射对class的操作:

1.获得类的相关信息
注:操作类的信息室,用带有Declared的方法能访问私有属性,方法,否则不能访问私有方法
类返回Class
属性返回Field
方法返回Method
构造函数返回Constructor
注解返回Annotation

操作方法基本一致:

package com.zlt.test1;

import java.lang.reflect.*;

/**
 * 用反射操作类
 * @author Administrator
 *
 */
public class OpterClass {
	public static void main(String[] args) throws Exception {
		Class cls=Class.forName("com.zlt.test1.AAA"); //1.得到类
		//获得类信息
		String name=cls.getName();//获取包名+类名
		String fullName=cls.getSimpleName();//获取类名
		
		//获得属性,返回Field类型
		Field f=cls.getDeclaredField("str1");//获取指定属性,能访问私有的
		System.out.println(f.getName());
		
		Field fid[]=cls.getFields();//获取属性,私有的访问不到
		for(Field ff:fid) {
			System.out.println(ff.getName());
		}
		
		//获取方法
		Method method=cls.getDeclaredMethod("Print", String.class);//  方法名,参数类型列表 --> 没有参数就无须添加
		Method []methods=cls.getDeclaredMethods();//获取全部方法,任何访问级别
		System.out.println(method.getName());
		
		//获取构造函数
		Constructor cons=cls.getConstructor(); //不需要跟方法名,直接给参数即可,也是参数的模板Class类
		System.out.println(cons.getName());
		
	}
}

class AAA{
	public String str1="aaa";
	private String str2="bbb";
	public AAA() {
		System.out.println("无参构造");
	}
	public AAA(String aaa) {
		this.str1=aaa;
	}
	public void Print(String a) {
		System.out.println("print");	
	}
}

在这里插入图片描述

注:(1)在获取属性,方法,构造函数时,如果要访问私有的,需使用带Declared的get方法
(2)在获取指定方法时,要传参,分别是方法名和参数的模板类(类名.calss),如果没有参数则只需要方法名
(3)获取构造方法时,直接以模板类(类名.calss)作为参数即可
(4)如果直接获取所有属性、方法、构造函数,则返回对应类型的数组

2.操作属性,方法,构造函数

package com.zlt.test1;

import java.lang.reflect.*;

public class OpterClass2 {
	public static void main(String[] args) throws Exception {
		Class cls=BBB.class;//获取Class对象
		Constructor<BBB> cons1=cls.getConstructor();//获取无参构造
		Constructor<BBB> cons2=cls.getConstructor(String.class);//获取有参构造
		
		//调用构造函数
		BBB b1=cons1.newInstance();
		BBB b2=cons2.newInstance("新新参数");
		
		//获取方法
		Method m1=cls.getDeclaredMethod("Print");//无参方法
		Method m2=cls.getDeclaredMethod("Print",String.class);//有参方法
		
		//使用方法
		m1.invoke(b1);//执行b1对象的无参方法
		m2.invoke(b1,"aaa");//执行b1对象的有参方法
		m1.invoke(b2);//执行b2对象的无参方法
		m2.invoke(b2,"aaa");//执行b2对象的有参方法
		
		//获取属性
		Field f=cls.getDeclaredField("name");
		
		//操作属性
		f.setAccessible(true);//操作私有属性要关闭安全检查
		f.set(b1, "new b1");//设置b1的name属性
		f.set(b2, "new b2");//设置b2的name属性
		m1.invoke(b1);
		m1.invoke(b2);
	}
}

class BBB{
	private String name="aaa";
	public BBB() {
		System.out.println("无参构造");
	}
	public BBB(String name) {
		this.name=name;
		System.out.println("有参构造");
	}
	public void Print() {
		System.out.println(this.name);
		System.out.println("调用无参方法");
	}
	public void Print(String a) {
		System.out.println("调用有参构造方法");
	}
}

结果如下:
在这里插入图片描述
注:(1)操作属性时,如果要访问私有属性,要关闭安全检查 -------- setAccessible(true)
(2)使用类的方法一般用构造函数newInstances创建对象操作,成员方法的使用都与对象离不开关系
(3)注意获得方法和使用方法传递的参数的区别

3.操作注解
步骤:
(1)先获得Class对象
(2)获得对应类、属性、方法…的注解,返回对应注解的类型
(3)获取注解的值

案例:把类映射成sql语句

先定义两个注解

package com.zlt.fluance;
/**
 * 表名信息
 */
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
	String data();//属于哪个数据库
	String name();//表名
}

package com.zlt.fluance;

/**
 * 表的每一列
 */
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
	String name();//列名
	String type();//数据类型
	int length() default 1;//长度
	String[] key() default "";//约束
}

用反射操作注解

package com.zlt.fluance;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

public class CreateTable {

	public String Create(Class cls) {
		String sql="";//sql语句
		Table table=(Table)cls.getAnnotation(Table.class);//获得类的注解
		String tableOfData=table.data();//表所在的数据库
		String tableName=table.name();//表名
		
		if(tableOfData!=null) sql+="use "+tableOfData+"\r";
		sql+="create table "+tableName +" (\n\t";
				
		Field[] f=cls.getDeclaredFields();
		for(int i=0;i<f.length;i++) {//遍历属性
			Field field=f[i];
			Column cloumn=field.getAnnotation(Column.class);//获得属性的注解
			String keys="";
			
			for(int k=0;k<cloumn.key().length;k++) {//添加约束
				keys+=" "+cloumn.key()[k];
			}
			String row="";//属性
			if(i==(f.length-1))
				row=cloumn.name()+" "+cloumn.type()+"("+cloumn.length()+")"+keys+"\r";
			else
				row=cloumn.name()+" "+cloumn.type()+"("+cloumn.length()+")"+keys+",\r\t";
			sql+=row;
		}
		sql+=");";
		return sql;
	}
}

函数调用

package com.zlt.fluance;
/**
 * 调用封装的函数
 * 把类映射出对应的sql语句
 * @author Administrator
 *
 */
public class Test {
	public static void main(String[] args) {
		CreateTable ct=new CreateTable();
		String sql=ct.Create(Student.class);
		System.out.println(sql);
	}
}

结果:
在这里插入图片描述

注:注解的使用遵循开头的三步走战略

总结:(1)反射操作的核心是Class对象,反射就是不断操作这个对象,再通过它的API来操作信息。
(2)反射会降低程序运行效率
在这里插入图片描述
(3)反射能大大提高程序开发效率,在企业常被使用,希望大家能掌握。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值