常见Annotation
使用 Annotation 时要在其前面增加 @ 符号, 并 把该 Annotation 当成
一个修饰符使用。用于修饰它支持的程序元素
package com.annotation.javadoc;
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方法()";
}
}
自定义注解
定义新的 Annotation 类型使用 @interface 关键字
自定义注解自动继承了java.lang.annotation.Annotation 接口
Annotation 的成员变量在 Annotation 定义中以无参数方法的形式来声明。其
方法名和返回值定义了该成员的名字和类型。我们称为配置参数。类型只能
是八种基本数据类型、String 类型 、Class 类型 、enum 类型 、Annotation 类型 、
以上所有类型的 数组。
可以在定义 Annotation 的成员变量时为其指定初始值, 指定成员变量的初始
值可使用 default 关键字
如果只有一个参数成员,建议使用 参数名为value
如果定义的注解含有配置参数,那么使用时必须指定参数值,除非它有默认
值。格式是“参数名 = 参数值”,如果只有一个参数成员,且名称为value,
可以省略“value=”
没有成员定义的 Annotation 称为 标记; 包含成员变量的 Annotation 称为元数
据 Annotation
注意:自定义注解必须配上注解的信息处理流程才有意义。
//定义一个注解
//@Target表示我们的注解可以用在那些地方
@Target(value={ElementType.METHOD,ElementType.Type})
//@Retention 表示我们的注解在什么地方有效 runtime>class>souces
@Retention(value=RetentionPolicy.RUNTIME)
//@Documented 表示是否将我们的注解声称在javadoc中
@Doucumented
//@Inherited 表示子类可以继承父类的注解
@Inherited
public @interface MyAnnotation{
}
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation{
//注解的参数 数据类型 参数名称 ();
//default 默认值
String naem() default "";
int age() default -1; // 默认值 -1 代表不存在
}
class Test{
public static void main(String[] args){
//调用注解
//注解可以显示赋值,如果没有默认值,必须赋值
@MyAnnotation()
public void test(){
}
}
}
正常方式:
引入需要的”包类”名称–》 通过new实例化 --》取得实例化对象
反射方式:
实例化对象 --》 getClass()方法 --》得到完整的“包类”名称
1 、动态语言
是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以
被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是 在运
行时代码可以根据某些条件改变自身结构。
主要动态语言:Object-C、C#、JavaScript、PHP、Python、Erlang。
2 、静态语言
与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、C、
C++。
Java反射机制提供的功能
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时获取泛型信息
在运行时调用任意一个对象的成员变量和方法
在运行时处理注解
生成动态代理
Java反射相关的API
java.lang.Class: 代表一 个 类
java.lang.reflect.Method: 代表类 的 方法
java.lang.reflect.Field: 代表类的 成员 变量
java.lang.reflect.Constructor: 代表类 的 构造 器
… …
Class类
Class类中常用的方法
获取Class类的实例
1) 前提:若已知具体的类,通过类的class属性获取,该方法最为安全可靠,
程序性能最高
实例: :Class clazz = String.class;
2) 前提:已知某个类的实例,调用该实例的getClass()方法获取Class对象
实例: :Class clazz = “www.atguigu.com”.getClass();
3) 前提:已知一个类的全类名,且该类在类路径下,可通过Class类的静态方
法forName()获取,可能抛出 ClassNotFoundException
实例: :Class clazz = Class.forName(“java.lang.String”);
4)其他方式(不做要求)
ClassLoader cl = this.getClass().getClassLoader();
Class clazz4 = cl.loadClass(“类的全类名”);
package com.it.demo03;
/**
* @author shkstart
* @create 2020-04-17 9:45
*/
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
System.out.println("名字为:" + person.name);
//方式一:已知对象的全类名 通过forName获取Class对象
Class c1 = Class.forName("com.it.demo03.Student");
//方式二:已知类的实例 通过getClass获取Class对象
Class c2 = person.getClass();
//方式三:已知类名 通过.class获取Class对象
Class<Student> c3 = Student.class;
System.out.println(c1.hashCode() + "\n" + c2.hashCode() + "\n" + c3.hashCode());
}
}
//实体类
class Person{
String name;
public Person(){}
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
class Student extends Person{
public Student(){
this.name = "学生";
}
}
class Teacher extends Person{
public Teacher(){
this.name = "老师";
}
}
那些类可以有Class对象
Class c1 = Object.class; //类
Class c2 = Comparable.class;//接口
Class c3 = String[].class;//一维数组
Class c4 = String[][].class; //二维数组
Class c5 = Override.class; // 注解
Class c6 = ElementType.class;//枚举
Class c7 = Integer.class;//基本数据类型
Class c8 = void.class; //void
Class c9 = Class.class; //Class
public class ClassLoadingTest {
public static void main(String[] args) {
System.out.println(A.m);
}
}
class A {
static {
m = 300;
}
static int m = 100;
}
//第二步:链接结束后m=0
//第三步:初始化后,m的值由()方法执行决定
// 这个A的类构造器()方法由类变量的赋值和静态代码块中的语句按照顺序合并
产生,类似于
// (){
// m = 300;
// m = 100;
// }
类的初始化
package com.it.demo03;
/**
* @author shkstart
* @create 2020-04-17 9:45
*/
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException {
//new一个类对象 会发生初始化
//如果父类没有初始化,先初始化父类
//Son son = new Son();
//反射也会使类初始化 java.lang.refect
//Class.forName("com.it.demo03.Son");
//-------------主动引用↑ 被动引用↓------------------------------
//子类引用父类的静态常量 会初始化父类 不会初始化子类
//System.out.println(Son.f);
//引用常量不会初始化
System.out.println(Son.S);
//定义数组不会初始化
Son[] sons = new Son[4];
}
static {
System.out.println("main方法被初始化");
}
}
class Father{
static int f = 100;
static {
System.out.println("Father类被初始化了");
}
}
class Son extends Father{
static {
System.out.println("Son类被初始化了");
m = 300;
}
static int m = 100;
static final int S = 10;
}
类加载器
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException {
//获取系统类加载器
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
System.out.println(classLoader);
//获取系统类加载器的父类加载器 即扩展类加载器
ClassLoader parent = classLoader.getParent();
System.out.println(parent);
//获取扩展类加载器父类加载器 即引导类加载器
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);
//测试当前类是由哪个类加载器进行加载
ClassLoader c1 = Test01.class.getClassLoader();
System.out.println(c1);
//测试JDK提供的Object类由哪个类加载器加载
c1 = Class.forName("java.lang.Object").getClassLoader();
System.out.println(c1);
//关于类加载器的一个主要方法:getResourceAsStream(String str):获取类路
//径下的指定文件的输入流
InputStream in = Test01.class.getClassLoader().getResourceAsStream("jdbc.properties");
System.out.println(in);
}
}
获取运行时类的完整结构
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
User user = new User();
Class c1 = user.getClass();
//获取类的名字
String name = c1.getName(); //获取完整类名
String simpleName = c1.getSimpleName();//获取简单类名
System.out.println("完全类名" + name);
System.out.println("简单类名" + simpleName);
//获取父类Class
c1.getSuperClass()
//获取类下所有属性
Field[] fields = c1.getFields(); //获取所有public修饰的属性
for (Field field : fields) {
System.out.println(field);
}
fields = c1.getDeclaredFields();//获取类下所有属性
for (Field field : fields) {
System.out.println(field);
}
// Field field = c1.getField("name");//获取指定public修饰的属性
// System.out.println(field);
Field field = c1.getDeclaredField("name");//获取指定类下属性
System.out.println(field);
//获取类下所有方法
Method[] methods = c1.getMethods();//获取类下所有public修饰的方法以及父类的方法
for (Method method : methods) {
System.out.println(method);
}
methods = c1.getDeclaredMethods(); //获取本类下所有方法
for (Method method : methods) {
System.out.println("#" + method);
}
Method getName = c1.getMethod("getName", null);//获取指定方法
Method setName = c1.getMethod("setName",String.class);
System.out.println(getName);
System.out.println(setName);
//获得构造器方法
Constructor[] constructors = c1.getConstructors();//获取所有public修饰的构造器方法
constructors = c1.getDeclaredConstructors(); //获取本类所有的构造器方法
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//获得指定public修饰的构造器方法
Constructor constructor = c1.getConstructor(String.class,int.class,int.class);
//获取指定的构造方法
constructor = c1.getDeclaredConstructor(String.class,int.class,int.class);
System.out.println(constructor);
}
}
class User{
private String name;
private int age;
private int id;
public User() {
}
public User(String name, int age, int id) {
this.name = name;
this.age = age;
this.id = id;
}
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 getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", id=" + id +
'}';
}
}
创建运行时类的对象
//通过无参构造创建对象
//要求类必须有无参构造方法
//要求类的无参构造方法权限足够
Class c1 = User.class;
c1.newInstance();
//通过有参构造创建对象
//获取本类指定参数的构造器
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
//通过构造器.newInstance 传入参数 获取对象
User user = (User) constructor.newInstance("卡莎",18,1);
System.out.println(user);
调用运行时类的指定结构
Class c1 = User.class;
//通过无参构造创建对象
User user = (User)c1.newInstance();
//调用运行类的方法
//获取指定方法
Method setName = c1.getDeclaredMethod("setName", String.class);
//通过invoke(); 传入参数执行方法 invoke:激活方法
// 参数 : (对象,方法的值)
setName.invoke(user,"卡卡");
System.out.println(user.getName());
//调用运行类的属性
Field name = c1.getDeclaredField("name");
//如果调用的属性为private修饰的
//我们需要将setAccessible 设置为true
//Accessible:启动和禁用访问安全检查的开关 true:禁用 false:开启
name.setAccessible(true);
//通过属性了的set或get方法进行取或存
//get 取得指定对象obj上此Field的属性内容
//set 设置指定对象obj上此Field的属性内容
name.set(user,"你好");
System.out.println(user.getName());
setAccessible()方法
Method和Field、Constructor对象都有setAccessible()方法。
setAccessible启动和禁用访问安全检查的开关。
参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。
提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被
调用,那么请设置为true。
使得原本无法访问的私有成员也可以访问
参数值为false则指示反射的对象应该实施Java语言访问检查。
获取泛型信息
public class Test01 {
public void test01(Map<String,Object> map, List<String> List){
System.out.println("test01");
}
public Map<String,Object> test02(){
System.out.println("test02");
return null;
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Class c1 = Test01.class;
//获取方法
Method method = c1.getDeclaredMethod("test01", Map.class, List.class);
//获取方法泛型参数化类型
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println(genericParameterType);
//判断是否为参数化类型
if(genericParameterType instanceof ParameterizedType){
//强转为参数化类型 获取真实参数类型的值
Type[] actualTypeArguments = ((ParameterizedType)genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
}
}
获取注解信息
public class Test01 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
//1.获取Class
Class c1 = Class.forName("com.it.demo03.Student");
//2.通过Class获的注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//3.获取注解的value值
Table table = (Table)c1.getAnnotation(Table.class);
System.out.println(table.value());
//获取属性注解的value
java.lang.reflect.Field id = c1.getDeclaredField("id");
Field field = id.getAnnotation(Field.class);
System.out.println(field.column());
System.out.println(field.length());
System.out.println(field.type());
}
}
@Table("db_student")
class Student{
@Field(column = "db_id", type = "int",length = 10)
private int id;
@Field(column = "db_name", type = "String",length = 10)
private String name;
@Field(column = "db_age", type = "int",length = 10)
private int age;
public Student() {
}
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Field{
String column();
String type();
int length();
}