A. 需要反射的类
package com.itheima02;
//妹子类
public class MeiZi {
private String name = "佳华MM";
private int age = 18;
@Override
public String toString() {
return "MeiZi{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//无参无返回值方法
private void say(){
System.out.println("say无参无返回值");
}
//有参有返回值方法
private String eat(int x,int y){
System.out.println("eat有参有返回值");
return "值:"+x+y;
}
}
B. 访问私有成员变量
//想要访问 私有成员变量 age 多大,并且把 age修改一下
public static void main(String[] args) throws Exception{
//【0】 (准备工作)获取到字节码的对象,并且创建 MeiZi的对象
Class<?> clazz = Class.forName("com.itheima02.MeiZi");
Object o = clazz.newInstance();
System.out.println("o = " + o); //o = MeiZi{name='佳华MM', age=18}
//【1】通过字节码获取 成员变量 Field
Field ageField = clazz.getDeclaredField("age");
//【2】暴力访问,强行摸
ageField.setAccessible(true);
//【3】修改值(参数1:对象,参数2:需要修改的值)
ageField.set(o,38);
//【4】查看值
Object age = ageField.get(o);
System.out.println("age = " + age); //age = 38
System.out.println("o = " + o);//o = MeiZi{name='佳华MM', age=38}
}
C. 访问私有成员方法
//想要访问 私有成员成员方法,并且调用
public static void main(String[] args) throws Exception{
//【0】 (准备工作)获取到字节码的对象,并且创建 MeiZi的对象
Class<?> clazz = Class.forName("com.itheima02.MeiZi");
Object o = clazz.newInstance();
//【1】通过字节码对象,获取方法的对象 Method
Method method01 = clazz.getDeclaredMethod("say");
//【2】设置暴力访问
method01.setAccessible(true);
//【3】调用方法
//参数1是 对象,上面的o.
method01.invoke(o); //say无参无返回值
//===========================
//【1】通过字节码对象,获取方法的对象 Method
Method method02 = clazz.getDeclaredMethod("eat",int.class,int.class);
//【2】设置暴力访问
method02.setAccessible(true);
//【3】调用方法
//参数1是 对象,上面的o.
Object fanhuizhi = method02.invoke(o, 66, 88);//eat有参有返回值
System.out.println("fanhuizhi = " + fanhuizhi);//fanhuizhi = 值:6688
}
1、注解的概念
A.注释: 给程序员看的
B.注解: 给Java程序看的
2、注解的作用
A.编写文档. javadoc java类
B.检查代码正确性 例如@Override检查是否正确覆盖重写
C.自定义注解,反射之后,设计Java框架
3、系统提供好的注解
A. @Override 检查是否是正确的覆盖重写
B. @FunctionalInterface 检查是否是正确的函数式接口
C. @Deprecated 检查标注的内容是否已经过时了
D. @SuppressWarnings("all") 压制所有的警告信息(防止处女座的)
4、自定义注解
A.格式:
public @interface 注解名称{ ... }
B.本质是一个接口
public interface 注解名称 extends Annotation{ .... }
C.反编译的操作
在cmd控制台当中 javap 类名称.class
5、注解的属性
注解的属性: 在本质为接口的注解里面,定义的抽象方法,我们称之为"属性"。定义注解的时候 变量赋值的格式很类似。
基本数据类型
String
枚举 (一堆常量的在一起)可以列举出来的
注解
以上类型的数组
注解属性的注意事项:
- 如果注解的属性名称是value , 并且只有它一个属性的时候,可以省略 value = 不写
- 如果注解的属性当中存在数组,并且数组的值,只有一个情况下,可以省略大括号不写
- 如果注解的属性,后面跟着 default 的关键字和值,可以省略赋值的操作
6、元注解(注解的注解)
A. @Target:描述注解能够作用的位置(使用频率高)
ElementType取值:
TYPE:可以作用于类上
METHOD:可以作用于方法上
FIELD:可以作用于成员变量上
B. @Retention:描述注解被保留的阶段(使用频率高)
@Retention(RetentionPolicy.RUNTIME):
当前被描述的注解,会保留到class字节码文件中,并被JVM读取到
C. @Documented:描述注解是否被抽取到api文档中
D. @Inherited:描述注解是否被子类继承
7、解析注解
A. 需要操作的类
package com.itheima04;
public class Car {
public void pao(){
System.out.println("汽车跑...");
}
}
B. 自定义注解
//自定义的注解
@Target(ElementType.TYPE) //注解只能加在类上
@Retention(RetentionPolicy.RUNTIME) //在运行时
public @interface MyZhuJie {
String className();
String methodName();
}
C.解析自定义注解
@MyZhuJie(className="com.itheima04.Car",methodName = "pao")
public class Test {
public static void main(String[] args) {
//[1]采用当前字节的对象,获取注解的对象,参数是 字节码对象.class
MyZhuJie zhujie = Test.class.getAnnotation(MyZhuJie.class);
//[2]调用成员方法,抽象方法
String cname = zhujie.className();
String mname = zhujie.methodName();
//====================
//打印输出结果
System.out.println("cname = " + cname); //cname = com.itheima04.Car
System.out.println("mname = " + mname); //mname = pao
}
}