java中反射和注解的简单使用方法

网友投稿 213 2022-10-08


java中反射和注解的简单使用方法

目录什么反射?java反射机制提供的功能反射相关的主要APIClass 类获取Class 类的实例( 四种方法)哪些类型可以有Class 对象?演示Class类的常用方法有了Class对象,能做什么?调用运行时类的指定结构1. 调用指定方法 关于setAccessible调用Class对象的newInstance()方法综合案例:注解什么是注解?常见的Annotation JDK 中的元注解自定义 Annotation最后通过反射获取注解信息:总结

什么反射?

Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为: 反射。

Java反射机制提供的功能

在运行时判断任意一个对象所属的类

在运行时构造任意一个类的对象

在运行时判断任意一个类所具有的成员变量和方法

在运行时获取泛型信息

在运行时调用任意一个对象的成员变量和方法

在运行时处理注解

生成动态代理

反射相关的主要API

java.lang.Class: 代表一 个 类

java.lang.reflect.Method: 代表类 的 方法

java.lang.reflect.Field: 代表类的 成员 变量

java.lang.reflect.Constructor: 代表类 的 构造

Class 类

对象照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个结构(class/interface/enum/annotation/primitive type/void/[])的有关信息

Class本身也是一个类

Class 对象只能由系统建立对象

 一个加载的类在 JVM 中只会有一个Class实例

一个Class对象对应的是一个加载到JVM中的一个.class文件

 每个类的实例都会记得自己是由哪个 Class 实例所生成

 通过Class可以完整地得到一个类中的所有被加载的结构

 Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的Class对象

Class类的常用方法

方法名

功能说明

static Class forName(String name) 

返回指定类名 name 的 Class 对象

Object newInstance()

调用缺省构造函数,返回该Class对象的一个实例

getName()

返回此Class对象所表示的实体(类、接口、数组类、基本类型

或void)名称

Class getSuperClass() 

返回当前Class对象的父类的Class对象

Class [] getInterfaces() 

获取当前Class对象的接口

ClassLoader getClassLoader() 

返回该类的类加载器

Class getSuperclass()

返回表示此Class所表示的实体的超类的Class

Constructor[] getConstructors() 

返回一个包含某些Constructor对象的数组

Field[] getDeclaredFields() 

返回Field对象的一个数组

Method getMethod(String

name,Class … paramTypes)

返回一个Method对象,此对象的形参类型为paramType

获取Class 类的实例( 四种方法)

先创建一个实体类

package com.chen.pojo;

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

@AllArgsConstructor

@NoArgsConstructor

@Data

public class Car {

public String brand="宝马";

public int price=500000;

public String color="白色";

}

1.前提:已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出 ClassNotFoundException

//1.Class.forName,应用场景:多用于配置文件,读取类全路径,加载类

String classAllPath="com.chen.pojo.Car";

Class> cls1=Class.forName(classAllPath);

2.前提:若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高

//2.类名.class,应用场景:用于参数传递

Class cls2 = Car.class;

System.out.println(cls2);

3.已知某个类的实例,调用该实例的getClass()方法获取Class对象

/3.对象.getClass(),应用场景,有对象实例

Car car=new Car();

Class cls3=car.getClass();

System.out.println(cls3);

4.其他方式(不做要求)

//4.通过类加载器(4)种来获取类的Class对象

//(1)先得到类加载器car

ClassLoader classLoader=car.getClass().getClassLoader();

//(2)通过类加载器得到Class对象

Class> cls4=classLoader.loadClass(classAllPath);

System.out.println(cls4);

//cls1,cls2,cls3,cls4 其实是同一个对象

System.out.println(cls1.hashCode());

System.out.println(cls2.hashCode());

System.out.println(cls3.hashCode());

System.out.println(cls4.hashCode());

//5. 基本数据(int,char,boolean,float,double,byte,long,short) 按如下方式得到Class类对象

Class integerClass=int.class;

Class characterClass=char.class;

Class booleanClass=boolean.class;

System.out.println(integerClass);

//6.基本数据类型对应的包装类,可以通过 .TYPE 得到class类对象

Class type1=Integer.TYPE;

Class type2 = Character.TYPE;//其它包装类BOOLEAN,DOUBLE,LONG,BYTE

System.out.println(type1);

哪些类型可以有Class 对象?

(1)class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类

(2)interface:接口

(3)[]:数组

(4)enum:枚举

(5)annotation:注解@interface

(6)primitive type:基本数据类型

(7)void

Class cls1=String.class;//外部类

Class cls2=Serializable.class;//接口

Class cls3 = Integer[].class;//数组

Class cls4 = float[][].class;//二维数组

Class cls5 = Deprecated.class;//注解

//枚举

Class cls6 = Thread.State.class;

Class cls7 = long.class;

Class cls8= void.class;

Class cls9 = Class.class;

System.out.println(cls1);

System.out.println(cls2);

System.out.println(cls3);

System.out.println(cls4);

System.out.println(cls5);

System.out.println(cls6);

System.out.println(cls7);

System.out.println(cls8);

System.out.println(cls9);

演示Class类的常用方法

package com.chen;

import com.chen.pojo.Car;

import java.lang.reflect.Field;

import java.util.Arrays;

import java.util.List;

//演示Class类的常用方法

public class Class02 {

public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {

String classAllPath="com.chen.pojo.Car";

//1.获取Car类对应的Class对象

//>表示不确定的Java类

Class> cls=Class.forName(classAllPath);

//2.输出cls

System.out.println(cls);//显示cls对象,是哪个类的Class对象 class com.chen.pojo.Car

System.out.println(cls.getClass());//输出cls运行类型 class java.lang.Class

//3.得到包名

System.out.println(cls.getPackage().getName());

//4.得到全类名

System.out.println(cls.getName());

//5.通过cls创建对象实例

Car car= (Car) cls.newInstance();

System.out.println(car);

//6.通过反射获取属性 brand

Field brand=cls.getField("brand");

System.out.println(brand.get(car));

//7.通过反射给属性赋值

brand.set(car,"奔驰");

System.out.println(brand.get(car));

//8.获取所有属性(字段)

Field[] fields=cls.getFields();

for (Field field:fields){

System.out.println(field.getName());

}

}

}

有了Class对象,能做什么?

通过反射获取运行时类类的完整结构

Field 、Method 、Constructor 、Superclass 、Interface 、Annotation(实现的全部接口  所继承的父类  全部的构造器  全部的方法  全部的Field)

1. 实现的全部接口

public Class>[] getInterfaces()

确定此对象所表示的类或接口实现的接口。

2. 所继承的父类

public Class Super T> getSuperclass()

返回表示此 Class 所表示的实体(类、接口、基本类型)的父类的

Class。

3. 全部的构造器

public Constructor[] getConstructors()

返回此 Class 对象所表示的类的所有public构造方法。

public Constructor[] getDeclaredConstructors()

返回此 Class 对象表示的类声明的所有构造方法。

Constructor类中:

 取得修饰符: public int getModifiers();

取得方法名称: public String getName();

 取得参数的类型:public Class>[] getParameterTypes();

4. 全部的方法

public Method[] getDeclaredMethods()

返回此Class对象所表示的类或接口的全部方法

 public Method[] getMethods()

返回此Class对象所表示的类或接口的public的方法

 Method类中:

 public Class> getReturnType()取得全部的返回值

 public Class>[] getParameterTypes()取得全部的参数

 public int getModifiers()取得修饰符

 public Class>[] getExceptionTypes()取得异常信息

5. 全部的Field

public Field[] getFields()

返回此Class对象所表示的类或接口的public的Field。

public Field[] getDeclaredFields()

返回此Class对象所表示的类或接口的全部Field。

 Field方法中:

public int getModifiers() 以整数形式返回此Field的修饰符

 public Class> getType() 得到Field的属性类型

 public String getName() 返回Field的名称。

6. Annotation 相关

get Annotation(Class annotationClass)

getDeclaredAnnotations()

7. 泛型相关

获取父类泛型类型:Type getGenericSuperclass()

泛型类型:ParameterizedType

获取实际的泛型类型参数数组:getActualTypeArguments()

8. 类所在的包 Package getPackage()

例:

package com.chen;

import java.lang.annotation.Annotation;

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

//演示如来通过反射获取类的结构信息

public class ReflectionUtils {

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {

//api_o1();

api_o2();

}

//第一组API

public static void api_o1() throws ClassNotFoundException, NoSuchMethodException {

//得到Class对象

Class> person=Class.forName("com.chen.Person");

//getName:获取全类名

System.out.println(person.getName());

//getSimpleName:获取简单类名

System.out.println(person.getSimpleName());

//getFields:获取所有public修饰的属性,包含本类以及父类的

Field[] fields=person.getFields();

for(Field field:fields){

System.out.println("本类以及父类的属性="+field.getName());

}

//getDeclaredFields:获取本类中所有属性

Field[] declaredFields = person.getDeclaredFields();

for(Field declaredField:declaredFields){

System.out.println("本类中所有属性="+declaredField.getName());

}

//getMethods:获取所有public修饰的方法,包含本类以及父类的

Method[] methods=person.getMethods();

for(Method method:methods){

System.out.println("本类及父类的方法="+method.getName());

}

//getDeclaredMethods:获取本类中所有的方法

Method[] declareMethods=person.getDeclaredMethods();

for(Method declareMethod:declareMethods){

System.out.println("本类中所有的方法:"+declareMethod);

}

//getConstructors:获取所有public修饰的构造器,包含本类

Constructor>[] constructors = person.getConstructors();

for(Constructor> constructor:constructors){

System.out.println("本类的构造器="+constructor.getName());

}

//getDeclaredConstructors:获取本类中所有的构造器

Constructor>[] declaredConstructors=person.getDeclaredConstructors();

for (Constructor> declaredConstructor:declaredConstructors){

System.out.println("本类中所有的构造器="+declaredConstructor.getName());

System.out.println("本类中所有的构造器="+declaredConstructor);

}

//getPackage:以Package形式返回 包信息

System.out.println(person.getPackage());

//getSuperClass:以Class形式返回父类信息

Class> superclass = person.getSuperclass();

System.out.println("以Class形式返回父类信息"+superclass);

//getInterfaces:以Class[]形式返回接口信息

Class>[] interfaces = person.getInterfaces();

for (Class> aninterface:interfaces){

System.out.println("接口信息"+aninterface);

}

//getAnnotat ions:以Annotation[]形式返回注解信息

Annotation[] annotations=person.getAnnotations();

for (Annotation annotation:annotations){

System.out.println("注解信息="+annotation);

}

}

public static void api_o2() throws ClassNotFoundException, NoSuchMethodException {

//得到Class对象

Class> person=Class.forName("com.chen.Person");

//getDeclaredFields:获取本类中所有属性

//规定说明:默认修饰符是0,public是1,private是2,protected是4,static是8,final是16,】 public(1)+static(8)=9

Field[] declaredFields = person.getDeclaredFields();

for(Field declaredField:declaredFields){

System.out.println("本类中所有属性="+declaredField.getName()+"该属性的修饰符="+declaredField.getModifiers()

+" 该属性的类型="+declaredField.getType());

}

//getDeclaredMethods:获取本类中所有的方法

Method[] declareMethods=person.getDeclaredMethods();

for(Method declareMethod:declareMethods){

System.out.println("本类中所有的方法:"+declareMethod

+" 该方法的访问修饰符="+declareMethod.getModifiers()

+" 该方法返回类型="+declareMethod.getReturnType());

//输出当前这个方法的形参数组情况

Class>[] parameterTypes=declareMethod.getParameterTypes();

for(Class> parameterType:parameterTypes){

System.out.println("该方法的形参类型="+parameterType);

}

}

//getDeclaredConstructors:获取本类中所有的构造器

Constructor>[] declaredConstructors=person.getDeclaredConstructors();

for (Constructor> declaredConstructor:declaredConstructors){

System.out.println("===============");

System.out.println("本类中所有的构造器="+declaredConstructor.getName());

System.out.println("本类中所有的构造器="+declaredConstructor);

Class>[] parameterTypes = declaredConstructor.getParameterTypes();

for(Class> parameterType:parameterTypes){

System.out.println("该构造器的形参类型="+parameterType);

}

}

}

}

interface IA{

}

interface IB{

}

class A {

public String hobby;

public void hi(){

}

public A() {

}

}

@Deprecated

class Person extends A implements IA,IB{

//属性

public String name;

protected int age;

String job;

private double sal;

public Person(){

}

public Person(String name)

{

}

private Person(String name,int age){

}

//方法

public void m1(String name,int age,double sal){

}

private void m2(){

}

protected void m3(){

}

void m4(){

}

public void m5(){

}

}

输出结果:

com.chen.Person

Person

本类以及父类的属性=name

本类以及父类的属性=hobby

本类中所有属性=name

本类中所有属性=age

本类中所有属性=job

本类中所有属性=sal

本类及父类的方法=m5

本类及父类的方法=m1

本类及父类的方法=hi

本类及父类的方法=wait

本类及父类的方法=wait

本类及父类的方法=wait

本类及父类的方法=equals

本类及父类的方法=toString

本类及父类的方法=hashCode

本类及父类的方法=getClass

本类及父类的方法=notify

本类及父类的方法=notifyAll

本类中所有的方法:public void com.chen.Person.m5()

本类中所有的方法:private void com.chen.Person.m2()

本类中所有的方法:void com.chen.Person.m4()

本类中所有的方法:public void com.chen.Person.m1(java.lang.String,int,double)

本类中所有的方法:protected void com.chen.Person.m3()

本类的构造器=com.chen.Person

本类的构造器=com.chen.Person

本类中所有的构造器=com.chen.Person

本类中所有的构造器=private com.chen.Person(java.lang.String,int)

本类中所有的构造器=com.chen.Person

本类中所有的构造器=public com.chen.Person(java.lang.String)

本类中所有的构造器=com.chen.Person

本类中所有的构造器=public com.chen.Person()

package com.chen

以Class形式返回父类信息class com.chen.A

接口信息interface com.chen.IA

接口信息interface com.chen.IB

注解信息=@java.lang.Deprecated()

本类中所有属性=name该属性的修饰符=1 该属性的类型=class java.lang.String

本类中所有属性=age该属性的修饰符=4 该属性的类型=int

本类中所有属性=job该属性的修饰符=0 该属性的类型=class java.lang.String

本类中所有属性=sal该属性的修饰符=2 该属性的类型=double

本类中所有的方法:public void com.chen.Person.m5() 该方法的访问修饰符=1 该方法返回类型=void

本类中所有的方法:private void com.chen.Person.m2() 该方法的访问修饰符=2 该方法返回类型=void

本类中所有的方法:void com.chen.Person.m4() 该方法的访问修饰符=0 该方法返回类型=void

本类中所有的方法:public void com.chen.Person.m1(java.lang.String,int,double) 该方法的访问修饰符=1 该方法返回类型=void

该方法的形参类型=class java.lang.String

该方法的形参类型=int

该方法的形参类型=double

本类中所有的方法:protected void com.chen.Person.m3() 该方法的访问修饰符=4 该方法返回类型=void

===============

本类中所有的构造器=com.chen.Person

本类中所有的构造器=private com.chen.Person(java.lang.String,int)

该构造器的形参类型=class java.lang.String

该构造器的形参类型=int

===============

本类中所有的构造器=com.chen.Person

本类中所有的构造器=public com.chen.Person(java.lang.String)

该构造器的形参类型=class java.lang.String

===============

本类中所有的构造器=com.chen.Person

本类中所有的构造器=public com.chen.Person()

调用运行时类的指定结构

1. 调用指定方法

通过反射,调用类中的方法,通过Method类完成。步骤:

1.通过Class类的getMethod(String name,Class…parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型。

2.之后使用Object invoke(Object obj, Object[] args)进行调用,并向方法中传递要设置的obj对象的参数信息。

Object invoke(Object obj, Object … args说明:

1.Object 对应原方法的返回值,若原方法无返回值,此时返回null

2.若原方法若为静态方法,此时形参Object obj可为null

3.若原方法形参列表为空,则Object[] args为null

4.若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法

例:

package com.chen;

//演示通过反射调用方法

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

public class ReflecAccessMethod {

public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

//1.得到Boss 类对应的class对象

Class> boossCls=Class.forName("com.chen.Boss");

//2.创建对象

Object o=boossCls.newInstance();

//3调用public的hi方法

Method hi=boossCls.getMethod("hi",String.class);

//3.1得到hi方法对象

Method hi2=boossCls.getDeclaredMethod("hi",String.class);

hi.invoke(o,"hhhh");

hi2.invoke(o,"hhhh2");

//4.调用private static 方法

//4.1得到say方法对象

Method say=boossCls.getDeclaredMethod("say", int.class, String.class, char.class);

//4.2因为say方法private,所以需要爆破,原理和前面讲的构造器和属性一样

say.setAccessible(true);

System.out.println(say.invoke(o,100,"栈说",'男'));

//4.3因为say方法是static,还可以这样用,可以传入null

System.out.println(say.invoke(null,200,"栈说2",'男'));

//5.在反射中,如果方法有返回值,统一返回Object,但是他运行类型和方法定义的返回值类型一致

Object invoke = say.invoke(null, 300, "小明", '男');

System.out.println("reVal的运行类型="+invoke);

}

}

class Boss{//类

public int age;

private static String name;

public Boss(){

}

private static String say(int n,String s,char c){

return n+" "+s+" " +c;

}

public void hi(String s){

System.out.println("hi "+s);

}

}

运行结果:

hi hhhh

hi hhhh2

100 栈说 男

200 栈说2 男

reVal的运行类型=300 小明 男

2.调用指定属性

在反射机制中,可以直接通过Field类操作类中的属性,通过Field类提供的set()和get()方法就可以完成设置和取得属性内容的操作。

public Field getField(String name) 返回此Class对象表示的类或接口的指定的public的Field。

 public Field getDeclaredField(String name)返回此Class对象表示的类或接口的指定的Field。

在 在Field 中:

public Object get(Object obj) 取得指定对象obj上此Field的属性内容

 public void set(Object obj,Object value) 设置指定对象obj上此Field的属性内容

例:

package com.chen;

import java.lang.reflect.Field;

//演示反射操作属性

public class RefleAccessProperty {

public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {

//1.得到Student类对应的class对象

Class> stuClass=Class.forName("com.chen.Student");

//2.创建对象

Object o=stuClass.newInstance();//o的运行类型就是student

System.out.println(o.getClass());

//3.使用反射得到age属性

Field age = stuClass.getField("age");

age.set(o,22);

System.out.println(o);

System.out.println(age.get(o));

//4.使用反射操作name属性

Field name = stuClass.getDeclaredField("name");

//对name进行爆破

name.setAccessible(true);

name.set(o,"小黑");

System.out.println(o);

System.out.println(name.get(o));

}

}

class Student{//类

public int age=20;

private static String name;

public Student(){

}

@Override

public String toString() {

return "Student{" +

"age=" + age + " name=" + name +

'}';

}

}

输出结果:

class com.chen.Student

Student{age=22  name=null}

22

Student{age=22  name=小黑}

小黑

关于setAccessible

Method和Field、Constructor对象都有setAccessible()方法。

 setAccessible启动和禁用访问安全检查的开关。

参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。

提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true。

 使得原本无法访问的私有成员也可以访问

参数值为false则指示反射的对象应该实施Java语言访问检查

调用Class对象的newInstance()方法

1)类必须有一个无参数的构造器。

2)类的构造器的访问权限需要足够。

例:

package com.chen;

import java.lang.reflect.Constructor;

import java.lang.reflect.InvocationTargetException;

//演示通过反射机制创建实例

public class ReflecCreateInstance {

public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

//1.先获取User类

Class> userClass = Class.forName("com.chen.User");

//2.通过public的无参构造器创建实例

Object o = userClass.newInstance();

System.out.println(o);

//3.通过public的参数构造器创建实例

/*constructor对象就是

public User(string name){

this.name=name;

}

* */

Constructor> constructor = userClass.getConstructor(String.class);

Object hh = constructor.newInstance("hh");

System.out.println("hh="+hh);

//4.通过非public的有参构造器创建实例

//4.1先得到private的构造器对象

Constructor> constructor1 = userClass.getDeclaredConstructor(int.class, String.class);

//4.2 创建实例

constructor1.setAccessible(true);//爆破,所有反射可以访问private构造器

Object user2=constructor1.newInstance(100,"小明");

System.out.println("user2="+user2);

}

}

class User{

private int age=10;

private String name="hello";

public User(){

}

public User(String name){

this.name=name;

}

private User(int age,String name){

this.age=age;

this.name=name;

}

@Override

public String toString() {

return "User{" +

"age=" + age +

", name='" + name + '\'' +

'}';

}

}

输出结果:

User{age=10, name='hello'}

hh=User{age=10, name='hh'}

user2=User{age=100, name='小明'}

综合案例:

例1:

/*定义PrivateTest类,有私有name属性,并且属性值为helloKitty

* 提供getName的公有方法

* 创建PrivateTest的类,利用Class类得到私有的name属性,修改私有的name属性值,并调用getName()的方法打印name属性值*/

package com.chen;

import java.lang.reflect.Field;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

public class HomeWork01 {

public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {

/*定义PrivateTest类,有私有name属性,并且属性值为helloKitty

* 提供getName的公有方法

* 创建PrivateTehttp://st的类,利用Class类得到私有的name属性,修改私有的name属性值,并调用getName()的方法打印name属性值*/

//1.得到PrivateTest类对应的class对象

Class privateTestClass = PrivateTest.class;

//2.创建对象实例

PrivateTest privateTest = privateTestClass.newInstance();

//3.得到name属性对象

Field name = privateTestClass.getDeclaredField("name");

//4.爆破name

name.setAccessible(true);

name.set(privateTest,"天龙八部");

//5.得到getName方法对象

Method getName = privateTestClass.getMethod("getName");

Object invoke = getName.invoke(privateTest);

System.out.println("name属性值"+invoke);

}

}

class PrivateTest{

private String name="hellokitty";

public String getName(){

return name;

}

}

例2

/*

* 利用class类的forName方法得到File类的cass对象

* 在控制台打印File类的所以构造器

* 通过newInstance的方法创建File对象,并创建E:\mynew.yxy文件

* */

package com.chen;

import java.lang.reflect.Constructor;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

public class HomeWork02 {

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

/*

* 利用class类的forName方法得到File类的class对象

* 在控制台打印File类的所以构造器

* 通过newInstance的方法创建File对象,并创建E:\mynew.yxy文件

* */

//1.class类的forName方法得到File类的class对象

Class> fileClass = Class.forName("java.io.File");

//2.得到所有的构造器

Constructor>[] declaredConstructors = fileClass.getDeclaredConstructors();

//遍历输出

for (Constructor> declaredConstructor:declaredConstructors){

System.out.println("file构造器="+declaredConstructor);

}

//3.指定的得到public java.io.File(java.lang.String)

Constructor> declaredConstructor = fileClass.getDeclaredConstructor(String.class);

String fileAllPath="D:\\mynew.txt";

Object file=declaredConstructor.newInstance(fileAllPath);

//4.得到createNewFile的方法对象

Method createNewFile = fileClass.getMethod("createNewFile");

createNewFile.invoke(file);

//file的运行类型就是File

System.out.println(file.getClass());

System.out.println("创建文件成功"+fileAllPath);

}

}

输出结果:

file构造器=public java.io.File(java.lang.String,java.lang.String)

file构造器=public java.io.File(java.lang.String)

file构造器=private java.io.File(java.lang.String,java.io.File)

file构造器=public java.io.File(java.io.File,java.lang.String)

file构造器=public java.io.File(java.net.URI)

file构造器=private java.io.File(java.lang.String,int)

class java.io.File

创建文件成功D:\mynew.txt

注解

什么是注解?

从 JDK 5.0 开始, Java 增加了对元数据(MetaData) 的支持, 也就是Annotation(注解)

Annotation 其实就是代码里的 特殊标记, 这些标记可以在编译, 类加载, 运行时被读取, 并执行相应的处理。通过使用Annotation, 程序员可以在不改变原有逻辑的情况下, 在源文件中嵌入一些补充信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或者进行部署。

Annotation 可以像修饰符一样被使用, 可用于 修饰包, 类, 构造器, 方 方法 法, 成员变量, 参数, 局部变量的声明, 这些信息被保存在 Annotation的“name=value” 对中

注解是一种趋势,一定程度上可以说:框架 = 注解 + 反射 + 设计模式。

常见的Annotation

示例一:生成文档相关的注解

@version 标明该类模块的版本

@see 参考转向,也就是相关主题

@since 从哪个版本开始增加的

@param 对方法中某参数的说明,如果没有参数就不能写

@return 对方法返回值的说明,如果方法的返回值类型是void就不能写

@exception 对方法可能抛出的异常进行说明 ,如果方法没有用throws显式抛出的异常就不能写

其中

@param @return 和 @exception 这三个标记都是只用于方法的。

@param的格式要求:@param 形参名 形参类型 形参说明

@return 的格式要求:@return 返回值类型 返回值说明

@exception的格式要求:@exception 异常类型 异常说明

@param和@exception可以并列多个

例:

/**

* @author shkstart

* @version 1.0

* @see Math.java

*/

public class JavadocTest {

/**

* 程序的主方法,程序的入口

* @param args String[] 命令行参数

*/

public static void main(String[] args) {

}

/**

* 求圆面积的方法

* @param radius double 半径值

* @return double 圆的面积

*/

public static double getArea(double radius){

return Math.PI * radius * radius;

}

}

示例二: 在编译时进行格式查 检查(JDK 内置的三个基本注解

@Override: 限定重写父类方法, 该注解只能用于方法

@Deprecated: 用于表示所修饰的元素(类, 方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择

@SuppressWarnings: 抑制编译器警告

例:

public class AnnotationTest{

public static void main(String[] args) {

@SuppressWarnings("unused")

int a = 10;

}

@Deprecated

public void print(){

System.out.println("过时的方法");

}

@Override

public String toString() {

return "重写的toString方法()";

}

}

示例三: 跟踪 代码依赖性,实现替代配置文件功能

@WebServlet("/login")

public class LoginServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws

ServletException, IOException { }

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws

ServletException, IOException {

doGet(request, response);

} }

JDK 中的元注解

JDK 的元 Annotation 用于修饰其他 Annotation 定义

JDK5.0提供了4个标准的meta-annotation类型,分别是:

RetentionTargetDocumentedInherited

1. Retention

@Retention: 只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 的生命周期, @Rentention 包含一个 RetentionPolicy 类型的成员变量, 使用

@Rentention 时必须为该 value 成员变量指定值:

ØRetentionPolicy.SOURCE:在源文件中有效(即源文件保留),编译器直接丢弃这种策略的注释

ØRetentionPolicy.CLASS:在class文件中有效(即class保留) , 当运行 Java 程序时, JVM不会保留注解。 这是默认值

ØRetentionPolicy.RUNTIME:在运行时有效(即运行时保留),当 当行 运行 Java 程序时, JVM 会 会保留注释。程序 可以通过反射获取 该注释。

2. Target

用于修饰 Annotation 定义, 用于指定被修饰的 Annotation 能用于修饰哪些程序元素。 @Target 也包含一个名为 value 的成员变量。

3. Documented

@Documented: 用于指定被该元 Annotation 修饰的 Annotation 类将被javadoc 工具提取成文档。默认情况下,javadoc是不包括注解的。

Ø定义为Documented的注解必须设置Retention值为RUNTIME。

4. Inherited

@Inherited: 被它修饰的 Annotation 将具有 继承性。如果某个类使用了被

@Inherited 修饰的 Annotation, 则其子类将自动具有该注解。

Ø比如:如果把标有@Inherited注解的自定义的注解标注在类级别上,子类则可以继承父类类级别的注解

Ø实际应用中,使用较少

自定义 Annotation

定义新的 Annotation 类型使用 @interface 关键字

l 自定义注解自动继承了java.lang.annotation.Annotation 接口

l Annotation 的成员变量在 Annotation 定义中以无参数方法的形式来声明。其方法名和返回值定义了该成员的名字和类型。我们称为配置参数。类型只能

是八种基本数据类型、String 类型 、Class 类型 、enum 类型 、Annotation 类型 、以上所有类型的 数组。

l 可以在定义 Annotation 的成员变量时为其指定初始值, 指定成员变量的初始值可使用 default 关键字

l 如果只有一个参数成员,建议使用 参数名为value

l 如果定义的注解含有配置参数,那么使用时必须指定参数值,除非它有默认值。格式是“参数名 = 参数值”,如果只有一个参数成员,且名称为value,可以省略“value=”

l 没有成员定义的 Annotation 称为 标记; 包含成员变量的 Annotation 称为元数据 Annotation

注意:自定义注解必须配上注解的信息处理流程才有意义。

例:

package com.chen.annotation;

import java.lang.annotation.*;

//自定义注解

@MyAnnotation2(id=1,name = "s")

public class MyAnnotation {

//注解可以显示,默认值,如果没有默认值,我们就必须给注解赋值

@MyAnnotation2(id=2,name = "小白",age=21,schools ={"中山大学" } )

public void test(){

}

@MyAnnotation3("小黑")

public void test2(){

}

}

@Target({ElementType.TYPE,ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@interface MyAnnotation2{

//注解的参数:参数类型+参数名();

String name() default "";

int age() default 0;

int id() ;

String[] schools() default {"清华大学","北京大学"};

}

@Target({ElementType.TYPE,ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@interface MyAnnotation3{

//注解的参数:参数类型+参数名();

String value() ;

}

最后通过反射获取注解信息:

package com.chen.annotation;

import java.lang.annotation.*;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

//注解和反射

public class AnnotationAndReflect {

public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {

Class> aClass = Class.forName("com.chen.annotation.Student");

//通过反射获得注解

Annotation[] annotations = aClass.getAnnotations();

for(Annotation annotation:annotations){

System.out.println(annotation);

}

//获得注解的value的值

TableStudent tableAnnotation = aClass.getAnnotation(TableStudent.class);

String value = tableAnnotation.value();

System.out.println(value);

//获得类指定的注解

Field f= aClass.getDeclaredField("name");

FieldStudent annotation = f.getAnnotation(FieldStudent.class);

System.out.println(annotation.columnName());

System.out.println(annotation.type());

System.out.println(annotation.length());

System.out.println("---------------");

Field f2= aClass.getDeclaredField("age");

FieldStudent annotation2 = f2.getAnnotation(FieldStudent.class);

System.out.println(annotation2.columnName());

System.out.println(annotation2.type());

System.out.println(annotation2.length());

System.out.println("---------------");

Field f3= aClass.getDeclaredField("id");

FieldStudent annotation3 = f3.getAnnotation(FieldStudent.class);

System.out.println(annotation3.columnName());

System.out.println(annotation3.type());

System.out.println(annotation3.length());

}

}

@TableStudent("db_student")

class Student{

@FieldStudent(columnName = "db_id",type = "int",length = 10)

private int id;

@FieldStudent(columnName = "db_age",type = "int",length = 10)

private int age;

@FieldStudent(columnName = "db_name",type = "varchar",length = 5)

private String name;

public Student() {

}

public Student(int id, int age, String name) {

this.id = id;

this.age = age;

this.name = name;

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

@Override

public String toString() {

return "Student{" +

"id=" + id +

", age=" + age +

", name='" + name + '\'' +

'}';

}

}

//类名的注解

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@interface TableStudent{

String value();

}

//属性的注解

@Target({ElementType.FIELD})

@Retention(RetentionPolicy.RUNTIME)

@interface FieldStudent{

String columnName();

String type();

int length();

}

输出结果

@com.chen.annotation.TableStudent(value=db_student)

db_student

db_name

varchar

5

---------------

db_age

int

10

---------------

db_id

int

10

总结


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:CVE-2020-1362 漏洞分析(Cve-2020-1472)
下一篇:开源=安全?RVN盗币事件复盘
相关文章

 发表评论

暂时没有评论,来抢沙发吧~