本章重点是ReflectTest7和ReflectTest10
p822 回顾反射机制
通过反射机制可以操作字节码文件,可以操作操作字节码创建对象。使程序更加灵活。
java.lang.reflect.*
java.lang.Class
java.lang.reflect.Method
java.lang.reflect.Constructor
java.lang.reflect.Field
1、Class c = Class.forName(“完整类名”)
2、Class c = 对象.getClass()
3、Class c = 类名.class()
Class c = Class.getClass(“java.util.Date”)
Object obj = c.newInstance()
需要注意的是newInstance底层调用的是该类的无参数构造方法。如果没有这个无参数构造方法,就会出现“实例化异常“
如果只想让一个方法的静态代码块执行,那么可以使用
Class.forName(完整类名)
这样类就加载了,类加载的时候静态代码块会执行
String path = Thread.currentThread().getContextClassLoader().get.Resource(“写从src出发的i相对路径”).getPath();
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(“从rsc出发的相对路径”)
ResourceBundle bundle = ResourceBundle.getBundle(“属性资源文件,注意不写扩展名”);
String className = bundle.getString(key);
System.out.println(key)
p823 获取Field【反射属性】
package com.bjpowernode.java.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ReflectTest05 {
public static void main(String[] args) throws Exception{
//首先拿到整个类
Class studentClass = Class.forName("com.bjpowernode.java.bean.Student");
//获取完整类名
System.out.println("完整名字:"+studentClass.getName());
//获取简单名字
System.out.println("简略名字:"+studentClass.getSimpleName());
//拿到所有的public修饰的Field:getFields()
Field[] fields = studentClass.getFields();
System.out.println(fields.length);
Field f = fields[0];//获取到的唯一的一个field是no,因为获取所有的public修饰的Field
String fieldName = f.getName();
System.out.println(fieldName);
//拿到所有的Field:getDeclaredFields()
//System.out.println(fs.length);
System.out.println("=========================================");
Field[] fs = studentClass.getDeclaredFields();
for (Field field : fs) {
//获取属性的名字
System.out.println(field.getName());
//获取属性的类型
Class fieldType = field.getType();
//String fName = fieldType.getName();
String fName = fieldType.getSimpleName();
System.out.println(fName);
//获取属性的修饰符列表
int i= field.getModifiers();//现在返回的修饰符是一个数字,怎么将他转换为字符串呢
//静态方法,要使用类名.方法名区调用
String fModifier = Modifier.toString(i);
System.out.println(fModifier);
}
System.out.println("=========================================");
}
}
p824 通过反射机制反编译一个类的Field属性【了解即可,不是重点】
package com.bjpowernode.java.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
//通过反射机制反编译一个类的Field
public class ReflectTest06 {
public static void main(String[] args) throws Exception{
//创建这个是为了拼接字符串
StringBuilder s = new StringBuilder();
//先拿到类
//Class studentClass = Class.forName("com.bjpowernode.java.bean.Student");
Class studentClass = Class.forName("java.lang.String");
//s.append("public class Student{");
//动态获取类名、动态获取修饰符
s.append(Modifier.toString(studentClass.getModifiers())
+" class "+studentClass.getSimpleName()+"{\n");
//拿到全部的Field
Field[] fields = studentClass.getDeclaredFields();
//遍历
for (Field field : fields){
s.append('\t');//追加换行符
s.append(Modifier.toString(field.getModifiers()));//追加修饰符
s.append(" ");//追加空格
s.append(field.getType().getSimpleName());//追加类型的简单名字
s.append(" ");//追加空格
s.append(field.getName());
s.append(";\n");//追加分号
}
s.append("}");
System.out.println(s);
}
}
p825 通过反射机制访问一个对象属性【掌握】
package com.bjpowernode.java.reflect;
import com.bjpowernode.java.bean.Student;
import java.lang.reflect.Field;
/*
通过反射机制访问java对象的属性?
*/
public class ReflectTest07{
public static void main(String[] args) throws Exception{
/*
不使用反射机制。怎么去访问对象属性'
=================================================
*/
Student student = new Student();
/*
给属性赋值
三要素:1、对象student
2、属性no
3、1234
*/
student.no=1234;
//读取属性
System.out.println(student.no);
/*
==================================================
*/
/*
使用反射机制,如何访问对象属性
/*
给obj对象(student)的no属性赋值
三要素:1、obj对象
2、noField属性
3、219912
==================================================
*/
Class studentClass = Class.forName("com.bjpowernode.java.bean.Student");
Object obj = studentClass.newInstance();//创建一个student对象(底层调用无参数构造方法)
//获取no属性(根据属性的名称来获取Field)
Field noField = studentClass.getDeclaredField("no");
//给属性赋值
noField.set(obj,219122);//给obj对象的no属性赋值219122
/*
获取属性的值,两个要素
1、obj对象
2、属性noField
*/
System.out.println(noField.get(obj));
/*
使用反射机制,如何访问对象属性
==================================================
*/
}
}
p826 访问对象属性【私有属性能否访问】
在这里插入图片描述
package com.bjpowernode.java.reflect;
import com.bjpowernode.java.bean.Student;
import java.lang.reflect.Field;
/*
通过反射机制访问java对象的属性?
*/
public class ReflectTest07{
public static void main(String[] args) throws Exception{
/*
不使用反射机制。怎么去访问对象属性'
=================================================
*/
Student student = new Student();
/*
给属性赋值
三要素:1、对象student
2、属性no
3、1234
*/
student.no=1234;
//读取属性
System.out.println(student.no);
/*
==================================================
*/
/*
使用反射机制,如何访问对象属性
/*
给obj对象(student)的no属性赋值
三要素:1、obj对象
2、noField属性
3、219912
==================================================
*/
Class studentClass = Class.forName("com.bjpowernode.java.bean.Student");
Object obj = studentClass.newInstance();//创建一个student对象(底层调用无参数构造方法)
//获取no属性(根据属性的名称来获取Field)
Field noField = studentClass.getDeclaredField("no");
//给属性赋值
noField.set(obj,219122);//给obj对象的no属性赋值219122
/*
获取属性的值,两个要素
1、obj对象
2、属性noField
*/
System.out.println(noField.get(obj));
//访问私有属性
Field nameField = studentClass.getDeclaredField("name");
//但是现在不能设置私有属性,如何访问私有属性呢?
//打破封装。但是有个缺点就是可能会带来安全隐患
//这样设置之后,在在外部可以访问private。
nameField.setAccessible(true);
//给name属性赋值
nameField.set(obj,"hajinwei");
//获取name属性
System.out.println(nameField.get(obj));
//但是现在不能设置私有属性,如何访问私有属性呢?
/*
使用反射机制,如何访问对象属性
==================================================
*/
}
}
p827 可变长度参数
package com.bjpowernode.java.reflect;
public class argsTest {
public static void main(String[] args) {
m();
m(12);
m(12,34);
//m("abc");编译报错
m3("abs","def","fdehf","gfg");
System.out.println("=============");
//可以直接传一个数组
String[] strs = {"dfhfj","dfshg","agyu","yurw"};
m3(strs);
System.out.println("=============");
//直接在参数列表new数组
m3(new String[]{"mazhognjie","hajinwei","zhangxinyue"});
}
public static void m(int...args){
System.out.println("m方法执行了");
}
//必须在最后,且只能有一个
public static void m2(int i,String...args){
//
}
public static void m3(String...args){
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
}
p828 反射机制的Method【了解】
package com.bjpowernode.java.reflect;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ReflectTets08 {
public static void main(String[] args) throws Exception{
//拿到类
Class userService = Class.forName("com.bjpowernode.java.service.UserService");
//创建一个userService对象
Object obj = userService.newInstance();
//拿到Method,包括私有的。
Method[] methods = userService.getDeclaredMethods();
//System.out.println(methods.length);
//遍历method
for (Method method : methods ){
//获取方法名
System.out.println(method.getName());
//获取返回值类型
System.out.println(method.getReturnType().getSimpleName());
//获取修饰符列表
System.out.println(Modifier.toString(method.getModifiers()));
//获取方法的修饰符列表(一个方法的参数可能有多个)
Class[] parameterTypes = method.getParameterTypes();
for (Class parametertype : parameterTypes){
System.out.println(parametertype.getSimpleName());
}
}
}
}
p829 反编译Method【了解】
package com.bjpowernode.java.reflect;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ReflectTets09 {
public static void main(String[] args) throws Exception{
//准备一个StringBuider类型用来拼接
StringBuilder s = new StringBuilder();
//拿到类的信息
//Class userServiceClass = Class.forName("com.bjpowernode.java.service.UserService");
Class userServiceClass = Class.forName("java.lang.String");
//s.append("public class userService {");
s.append(Modifier.toString(userServiceClass.getModifiers())
+" class "+userServiceClass.getSimpleName()+"{");
//获取方法
//拿到Method,包括私有的。
Method[] methods = userServiceClass.getDeclaredMethods();
for (Method method: methods){
//public boolean login(String name,String password){}
//获取修饰符列表(public)
s.append('\n');
s.append('\t');
s.append(Modifier.toString(method.getModifiers())+" ");
//获取返回值类型
s.append(method.getReturnType()+" ");
//获取方法名
s.append(method.getName()+"(");
//获取参数类型及参数名String name,String password
Class[] parameterTypes = method.getParameterTypes();
for (Class parametertype : parameterTypes){
//获取参数类型
s.append(parametertype.getSimpleName()+" ");
s.append(",");
//获取参数名字
// s.append(parametertype.get);
}
s.deleteCharAt(s.length() - 1);//删去第二个逗号。删除指定下标的字符
s.append(")");
}
s.append("\n}");
System.out.println(s);
}
}
p830 反射机制调用方法【重点】
package com.bjpowernode.java.reflect;
import com.bjpowernode.java.service.UserService;
import java.lang.reflect.Method;
/**
* 通过反射机制调用方法
*/
public class ReflectTest10 {
public static void main(String[] args) throws Exception{
/*
不使用反射机制如何调用方法
*/
//创建对象,调用方法
UserService userService = new UserService();
boolean loginSuccess = userService.login("admin","123456");
//System.out.println(loginSuccess);
System.out.println(loginSuccess ? "登录成功" : "登录失败");
userService.logout();
/*
使用反射机制调用方法
三要素:
1、对象userService
2、login方法名
3、实参列表
4、返回值
*/
//拿到类
Class serService = Class.forName("com.bjpowernode.java.service.UserService");
//创建对象
Object obj = serService.newInstance();//创建一个student对象(底层调用无参数构造方法)
//拿到方法名
Method loginMethod = userService.getClass().getDeclaredMethod("login", String.class, String.class);
//开始调用。
Object retValue = loginMethod.invoke(obj,"admin","123456");
System.out.println(retValue);
}
}
p831 反射Constructor
package com.bjpowernode.java.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
/*
通过反射机制反编译
*/
public class ReflectTest11 {
public static void main(String[] args) throws Exception{
//创建字符串用来拼接
StringBuilder s = new StringBuilder();
//拿到类
Class vipClass = Class.forName("java.lang.String");
s.append(Modifier.toString(vipClass.getModifiers())+" class "+vipClass.getSimpleName()+"{\n");//public+
//s.append("public class Vip {\n");
/*
拼接构造方法
*/
Constructor[] constructors = vipClass.getConstructors();
for (Constructor constructor :constructors){
s.append("\t");
//获取修饰符
s.append(Modifier.toString(vipClass.getModifiers()));
//构造方法无返回值,获取方法名
s.append(" "+vipClass.getSimpleName()+"(");
//获取参数列表
Class[] parameterTypes = constructor.getParameterTypes();
for (Class parameterType : parameterTypes){
//获取参数修饰列表
s.append(parameterType.getSimpleName()+" ");
//获取参数名
s.append(",");
}
//s.deleteCharAt(s.length() - 1);//删除参数中的逗号时,这样删除会出现错误。public Vip){}所以删除之前需要判断参数列表长度,如果参数大于1才删除
if (parameterTypes.length > 1){
s.deleteCharAt(s.length() - 1);
}
s.append("){}\n");
}
s.append("}");
System.out.println(s);
}
}
p832 反射机制调用构造方法【非重点】
package com.bjpowernode.java.reflect;
import com.bjpowernode.java.bean.Vip;
import java.lang.reflect.Constructor;
import java.util.concurrent.ExecutionException;
/*
使用反射机制new对象
*/
public class ReflectTest12 {
public static void main(String[] args) throws Exception {
/*
不使用反射机制new对象
*/
Vip vip1 = new Vip();
Vip vip2 = new Vip(123);
Vip vip3 = new Vip(1234,"mazhongjie");
Vip vip4 = new Vip(12345,"hgajinwei","19970410",true);
/*
使用反射机制创建对象
*/
//拿到类
Class c = Class.forName("com.bjpowernode.java.bean.Vip");
//调用无参数构造方法
Object obj = c.newInstance();
System.out.println(obj);
//调用带参数构造方法
//先获取到这个有参数的构造方法
Constructor constructor = c.getDeclaredConstructor(int.class,String.class,String.class,boolean.class);
//调用构造方法new对象
Object newobj = constructor.newInstance(110,"jack","1997-04-10",true);
System.out.println(newobj);
//获取无参构造方法
Constructor con2 = c.getDeclaredConstructor();
Object newobj2 = con2.newInstance();
System.out.println(newobj2);
}
}
p833 获取父类和父接口
反射机制结束
p834 注解怎么定义,怎么使用
p835 override注解【jdk内置注解】
java.lang下的注解
override方法只能注解方法。
p836 元注解【注解注解的注解】
p837 Deprecated注解
package com.bjpowernode.java.annotation;
//表示这个类已经过时
@Deprecated
public class AnnotationTest03 {
public static void main(String[] args) {
}
@Deprecated
public static void doSome(){
System.out.println("do something");
}
public static void doOther(){
System.out.println("do Other");
}
}
class T{
public static void main(String[] args) {
AnnotationTest03 at = new AnnotationTest03();
at.doSome();
AnnotationTest03.doOther();
AnnotationTest03.doSome();
}
}
p838 注解中定义属性
p839 属性是value时可以忽略
p840 value属性的忽略
可以省略的前提是前面的注解中只有一个属性,并且是value。不能有多个。
p841 属性是一个数组
p842 反射注解
package com.bjpowernode.java.annotation5;
//只允许该注解可以标注类,方法
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//Target元注解时一个value数组,其中的数组是一个枚举类型。ElementType.Type表示只能注解类。
@Target(value = {ElementType.TYPE,ElementType.METHOD})
//希望这个注解可以被反射
@Retention(RetentionPolicy.RUNTIME)
//@Retention(RetentionPolicy.SOURCE)
public @interface MyAnnotation {
/*
vaule属性
*/
String value() default "北京大兴区";
}
package com.bjpowernode.java.annotation5;
@MyAnnotation("上海浦东区")
public class MyAnnotationTest {
//不能注解Field
// @MyAnnotation
// int i;
//不能出现在构造方法上
// @MyAnnotation
// public MyAnnotationTest() {
// }
@MyAnnotation
public void doSome(){
}
}
package com.bjpowernode.java.annotation5;
//反射机制反射
public class ReflectAnnotationTest {
public static void main(String[] args) throws Exception{
//拿到类
Class c = Class.forName("com.bjpowernode.java.annotation5.MyAnnotationTest");
//判断MyAnnotationTest类上面是否有Annotation
System.out.println(c.isAnnotationPresent(MyAnnotation.class));//true
//如果有注解,如何获取注解
if (c.isAnnotationPresent(MyAnnotation.class)){
//获取该注解对象
MyAnnotation myAnnotation = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
//拿到注解对象
System.out.println("类上面的注解对象:"+myAnnotation);
//获取注解对象的属性,和调接口没区别
String value = myAnnotation.value();
System.out.println(value);
}
//判断String类上面是否有Annotation
Class stringClass = Class.forName("java.lang.String");
System.out.println(stringClass.isAnnotationPresent(String.class));//false
}
}
p843 通过反射获取注解对象属性的值
package com.bjpowernode.java.annotation6;
import com.bjpowernode.java.annotation4.MyAnnotation;
import java.lang.reflect.Method;
public class MyAnnotationTest {
@Myannotation(username = "admin",password = "454545")
public void doSome(){
}
public static void main(String[] args) throws Exception{
//通过反射机制取注解上的属性值
//第一步,拿到类
Class c = Class.forName("com.bjpowernode.java.annotation6.MyAnnotationTest");
//System.out.println(c.getName());
//拿到doSome()方法
Method doSomeMethod = c.getDeclaredMethod("doSome");
//判断该方法上是否有注解?
if (doSomeMethod.isAnnotationPresent(Myannotation.class)){
//如果有注解,如何拿到注解.使用doSomeMethod.getAnnotation()拿到Annotation类型的注解,
// 然后强转为MyAnnotation类型。
Myannotation myannotation = (Myannotation)doSomeMethod.getAnnotation(Myannotation.class);
//拿到doSome()方法上的注解对象属性
System.out.println(myannotation.username());
System.out.println(myannotation.password());
}
}
}
package com.bjpowernode.java.annotation6;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Myannotation {
/**
* username属性
*
*/
String username();
/**
* password属性
*
*/
String password();
}
p844 注解在实际开发中的作用
参考这个案例
完结2021.4.7