当前位置: 首页 > wzjs >正文

阿里域名注册网站学平面设计怎么样啊

阿里域名注册网站,学平面设计怎么样啊,百度主页,电脑编程培训反射Reflect 常规我们使用类的方法都是在代码中创建指定类型的实例如Apple apple new Apple(),这种写法要求我们在程序执行之初就确定好要使用的类和具体方法,扩展性和灵活性不足。 反射机制(Reflect)则是一种程序执行时冬天获取…

反射Reflect

常规我们使用类的方法都是在代码中创建指定类型的实例如Apple apple = new Apple(),这种写法要求我们在程序执行之初就确定好要使用的类和具体方法,扩展性和灵活性不足。
反射机制(Reflect)则是一种程序执行时冬天获取类和执行方法的能力,该方法突破了Java编译时确定类型的限制,为动态编程提供了底层支持,很多主流框架如Spring的底层都使用反射实现。

首先通过一个例子直观感受下正向和反射的区别:

public class Reflect {public static void main(String[] args) throws Exception{Person p = new Person("Kevin",19);System.out.println(p.toString());// 反向构造,获取类Class c = Class.forName("Reflect.Person");// 创建实例Object pe = c.newInstance();// 获取方法Method sout = c.getMethod("toString");System.out.println(sout.invoke(pe));}
}

下面详细介绍反射的使用方法。

创建class对象

JVM会为每一个类型生成一个元数据对象class,该对象存储了类型的完整信息,成员、方法等,反射机制通过该元数据对象实现对类的操作,进而实现动态编程,因为该过程需要借助class进行,好像一面镜子,所以该操作称为反射。

创建class对象有三种方法:

  1. Class.forName()全限定类名。示例为Class c=Class.forName("Reflect.Person");,全限定类名表示包含包位置的类路径,类似相对位置,但省略表示路径的符号和文件类型标记。
  2. 实例的getclass方法。示例Class p = new Person().getClass();使用实例对象的getClass方法获取元数据对象。
  3. 类的class属性。实例Class p1=Person.class;,使用类的class属性赋值。

获得构造信息及调用

// 获得构造函数,默认无参
Constructor c1=c.getConstructor();
// 针对重载函数,限定参数为指定类型的class
Constructor c2=c.getConstructor(String.class,int.class);
// 使用构造函数创建实例,默认无参构造
Object a=c2.newInstance("kevin",25);

获取类的属性及赋值

// 获取公开属性
Field name=c.getField("name");
// 获取私有属性
Field age=c.getDeclaredField("age");
// 获取属性列表
Field[] list=c.getFields();
Field[] list=c.getDeclaredFields()
// 打破私有封装
age.setAccessible(true);
// 修改实例的指定属性
age.set(a,26)

获取方法信息及调用

// 获取方法
Method getName=c.getMethod("getName");
// 执行方法
getName.invoke(对象,参数)
// 重载方法的获取,方法名,参数类型.class
Method setName=c.getMethod("setName",String.class);

在获取方法的getMethod源码我们看到是这样定义的public Method getMethod(String name, Class<?>... parameterTypes),所以这里补充一个知识,不定长参数
不定长参数可以表示为类型...参数名,这种定义方法表示输入该类型的参数有任意个都可以,简单示例如下:

    public static void out(String...para){for(int i=0;i<para.length;i++){System.out.println(para[i]);}}public static void main(String[] args) throws Exception{// 参数传多少个字符串都可以out("hello","world");}

可变长参数本质是基于列表实现的,该参数没有强制性,执行时可传可不传,但要放在参数列表的最后。

其他常用方法

作用用法
类加载器Classloader cl=class.getClassLoader()
获取类名getSimpleName()简类名,getName()获取全类名
获取修饰符getModifiers()获取修饰编号,Modifier.toString()转为修饰字符串
获取数据类型getReturnType()方法返回值类型、getParameterTypes()获得方法参数类型,getType()属性类型
获取父接口getInterfaces()
获取父类getSuperclass()

注解Annotation

注解是一种描述程序元素(类、属性、方法等)的机制,注解本身不影响程序运行,但程序可以获取注解以进行更改运行模式等操作,简单来说就是程序可读的注释

注解的使用方法为@注解名,我们在多线程部分重写run方法时,方法上的@override就是重写注解。

系统注解

编码过程中常用的注解有:
interface定义注解;
Override重写注解,有该注解标识的方法编译器会检查是否真的覆写了父类方法;
Deprecated不建议使用的方法,该注解标识的方法在调用时会有删除线显示,显示效果如下:
Deprecated不推荐使用的方法效果

自定义注解

注解是Java的基本文件之一,通过创建类给出的文件类型就能看出:
创建注解
自定义注解的方法是使用@interface关键字,直接给出示例:

public @interface MyAnnotation {// 注解内的成员变量需要(),可用default 设置默认值,否则需在添加注解时显式指定String value() default "nobody";
}
// 注解修饰Person类,当注解成员为value时可省
@MyAnnotation("person1")
public class Person {private String name;private int age;public static void main(String[] args) {Class clazz = Person.class;Annotation annotation=clazz.getAnnotation(MyAnnotation.class);System.out.println(annotation.toString());}
}
// 输出为@Annotation.MyAnnotation(value=person1)

元注解

即修饰注解的注解,元注解限制了注解能修饰哪些类型的元素,类、成员或者方法,同时规定了注解的作用域。

Target注解,表明注解的作用域。参数为ElementType,多个作用域需用{}包围,其关键字表示不同作用域,分别为:

ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
ElementType.CONSTRUCTOR 可以给构造方法进行注解
ElementType.FIELD 可以给属性进行注解
ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
ElementType.METHOD 可以给方法进行注解
ElementType.PACKAGE 可以给一个包进行注解
ElementType.PARAMETER 可以给一个方法内的参数进行注解
ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举

Retention注解,表明注解的声明周期。参数为RetentionPolicy,关键字表示的不同生命周期为:

RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃。
RetentionPolicy.CLASS 注解只被保留到编译进行的时候,即保存到class字节码文件中,它并不会被加载到 JVM 中。
RetentionPolicy.RUNTIME 注解可以保留到程序运行,它会被加载进入到 JVM 中,所以在程序运行时可以通过反射获取。

案例—反射获取添加Controller注解的私有成员

通过上面的学习我们了解到,注解应该是与反射共同作用,注解可作为程序元素的进一步补充说明,在反射过程中被获取执行,我们尝试结合反射与注解编写一个案例,首先自定义Controller注解,用于修饰指定的类,反射读取类的过程中检查是否有该注解修饰,有则获取其私有成员id

背景为有PersonAnimal两个类,Controller注解有一成员value默认为nobody,修饰两个类时该成员会变为personanimal,要求利用反射机制,找到Controller注解修饰后成员为person的类的有私有成员id的类,找到后给出提示。
实现的大致思路为:

  1. 读取配置文件,获取要识别类的信息,使用Properties和流对象FileReader实现。
  2. 将读取到的类信息按;分割成字符串数组,for循环分别判定。
  3. 根据类信息反射读取class对象,并获得注解信息。
  4. 注解内循环寻找类型为Controller的注解,找到后判定值是否为person
  5. 获取所有成员变量,循环检测权限修饰符是否有private,成员名称是否为id
  6. 找到符合条件的输出提示信息。

Animal类雷同,实现代码如下:

@Controller("person")
public class Person {private String name;private int age;private int id;public Person(String name, int age, int id) {this.name = name;this.age = age;this.id = id;}public String getName() {return name;}public int getAge() {return age;}public int getId() {return id;}public static void main(String[] args) {try {FileReader fr =new FileReader("config.properties");Properties prop = new Properties();prop.load(fr);String name = prop.getProperty("classname");String[] classNameArray = name.split(";");for(String className : classNameArray) {Class aclass=Class.forName(className);Annotation[] annotations = aclass.getAnnotations();for(Annotation annotation : annotations) {if(annotation instanceof Controller) {Controller myAnnotation = (Controller) annotation;if(myAnnotation.value().equals("person")) {Field[] declaredField=aclass.getDeclaredFields();for(Field field : declaredField) {if(field.getName().equals("id") && Modifier.toString(field.getModifiers()).contains("private")) {System.out.println("发现目标,当前类为:"+aclass.getTypeName());}}}}}}} catch (FileNotFoundException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}
}

总结

本文介绍了Java动态操作类的方法反射,以及给类添加信息的注解,反射提供了不同于传统正向先定义再使用类的方法,允许开发者逆向构建实例,并根据注解选择要执行的操作,其本质仍然是基于提高扩展性的设计

提高扩展性比较简单的方法是使用多态,二者之间有什么区别和联系呢?

首先回顾多态。允许父类接受子类实例,这也允许我们无需精准定义类型即可允许程序,只是不能调用子类方法,我们通过instanceof判断类型并向下转型即可解决,好像也很方便,但多态的扩展性是有前提的——继承链

多态的类型宽松仅针对已知继承链内的类,这要求开发者在开发时就设计好所有类的继承关系,并体现在代码中,反射机制可以实现真正突破编译限制,允许在​​运行时动态操作任意类的元数据,直接调用子类方法而无需转型,甚至直接操作私有成员,是更自由的操作手段。

反射在提供自由的同时也带来了安全风险:

  1. 打破封装。封装性是面向对象三大核心特征之一,反射操作私有成员的能力直接打破了这一特性,私有成员的更改可能导致类的内部问题。
  2. 代码注入。恶意代码可能通过Class.forName("恶意类名")加载和执行其他类,绕过编译检查。
  3. 性能开销。反射结构需要动态解析类的结构,带来效率问题,性能敏感场景可能不符合要求。

所以总得来说,反射还是应该少用,不得已要用的地方也要做好校验。


文章转载自:

http://zGShdBNN.kmcfw.cn
http://8DdVq22f.kmcfw.cn
http://VVAwor2a.kmcfw.cn
http://Smswq9Yr.kmcfw.cn
http://5tFaDrme.kmcfw.cn
http://a8wFQDhu.kmcfw.cn
http://RsTpCLhz.kmcfw.cn
http://xoFVRzMh.kmcfw.cn
http://Io8ck2pZ.kmcfw.cn
http://xCdsu01M.kmcfw.cn
http://2PQ6pNZ4.kmcfw.cn
http://rJwFxuUS.kmcfw.cn
http://H6AJrEQk.kmcfw.cn
http://ev0Ut95I.kmcfw.cn
http://uZ7MT9pm.kmcfw.cn
http://u4c8Qk8I.kmcfw.cn
http://X0TSyzSf.kmcfw.cn
http://YHIw9MlJ.kmcfw.cn
http://SS1K6QN4.kmcfw.cn
http://viVyOGKL.kmcfw.cn
http://h5OOz6sH.kmcfw.cn
http://OzqNk2QL.kmcfw.cn
http://NtfNMWgz.kmcfw.cn
http://J1tyKgio.kmcfw.cn
http://8bzjDxw1.kmcfw.cn
http://yOnhebjr.kmcfw.cn
http://fOBeTRmV.kmcfw.cn
http://wIUwSLKg.kmcfw.cn
http://Cc2tOvqg.kmcfw.cn
http://JJXHCClT.kmcfw.cn
http://www.dtcms.com/wzjs/637785.html

相关文章:

  • 网站搭建服务器网络域名后缀
  • 广州做网站哪家好公司网站打不开了
  • 网站建设公司怎么做的怎么做万网网站
  • 海搜网做的网站怎么样电子邮箱网站注册
  • 学院网站建设的需求分析深圳买门的网站建设
  • 玉林网站建设培训网站建设与管理培训总结
  • 灵璧网站建设wordpress 设置404
  • 自己电脑做网站服务器广域网访问山东公司网站开发
  • 设计师的网站网站维护要学多久
  • 电商设计的工作内容肇庆网站关键词优化
  • 厦门市建设与管理局 官方网站贵州省建设厅考证官方网站
  • 网站设计网站设计网站设计如何搭建购物平台
  • 中文网站建设技术wordpress论坛查看用户密码
  • 湖南张家界网站建设旅游示范校建设专题网站
  • 重庆做蔬菜配送的网站有哪些修改wordpress模板
  • 成都网站建设司能打开所有网址的浏览器
  • 手机网站你懂wordpress插件的安装目录
  • 网站建设与管理需要哪些证书想接做网站的单子
  • html怎么做网站首页2021年中国十大电商平台排名
  • 佛山免费网站建设seo 网站树
  • 专业网站建设设计考研培训机构排名前十
  • 怎样做网站背景网站生成pc应用
  • 安徽索凯特建设工程有限公司网站天津 论坛网站制作公司
  • 自贡住房和城乡建设厅网站vps网站打开需要身份验证
  • 邯郸网络运营中心电话多少郑州seo公司
  • 网站代理怎么设置免费网络推广网站大全
  • 做网站买什么笔记本好个人简历表格模板
  • 华为公司网站建设方案上海网站建设开发
  • 做设计的一般在什么网站找素材公司logo墙
  • 茂名网站建设托管用爬虫做数据整合网站