2022.08.16 java学习

1.反射
  • 反射是指对于任何一个Class类,在“运行的时候”都可以直接得到这个类的全部成分;这种运行时动态获取类信息以及动态调用类中成分的能力称为Java的反射机制
  • 在运行时获取类的字节码文件对象(Class文件),然后解析类中的全部成分
2.反射获取Class类对象
  • 源代码阶段:Class.forName(String className)
    • 其中className为全限名:包名+类名
  • Class对象阶段:类名.class
  • Runtime运行时阶段:对象.getClass()
3.反射获取构造器对象

Class类中用于获取构造器的方法:

方法说明
Constructor<?>[ ] getConstructors()返回所有构造器对象的数组(只能拿public的)
Constructor<?>[ ] getDeclaredConstructors()返回所有构造器对象的数组,存在就能拿到
Constructor< T> getConstructor(Class<?>… parameterTypes)按照参数类型定位并返回单个构造器对象(只能拿public的)
Constructor< T> getDeclaredConstructor(Class<?>… parameterTypes)返回单个构造器对象,存在就能拿到

Constructor类中用于创建对象的方法:

方法说明
T newInstance(Object… initargs)根据指定的构造器创建对象
public void setAccessible(boolean flag)设置为true,表示取消访问检查(private),进行暴力反射
4.反射获取成员变量对象
  • 先获取类对象,然后从类对象中获取类的成分对象

Class类中用于获取成员变量的方法:

方法说明
Field[ ] getFields()返回所有成员变量对象的数组(只能拿public)
Field[ ] getDeclaredFields()返回所有成员变量对象的数组,存在就能拿到
Field getField(String name)返回单个成员变量对象(只能拿public的)
Field getDeclaredField(String name)返回单个成员变量对象,存在就能拿到

Field类中用于取值、赋值的方法

方法说明
void set(Object obj, Object value)赋值
Object get(Object obj)取值

如果某成员变量是非public的,需要打开权限进行暴力反射,然后再取值、赋值;setAccessible(boolean)

5.反射获取方法对象

Class类中用于获取成员方法的方法

方法说明
Method[ ] getMethods()返回所有成员方法对象的数组(只能拿public的)
Method[ ] getDeclaredMethods()返回所有成员方法对象的数组,存在就能拿到
Method getMethod(String name, Class<?>… parameterTypes)返回单个成员方法对象(只能拿public的)
Method getDeclaredMethod(String name, Class<?>… parameterTypes)返回单个成员方法对象,存在就能拿到

Method类中用于触发执行的方法

方法说明
Object invoke(Object obj, Object… args)运行方法,参数一:用obj对象调用该方法;参数二:调用方法的传递的参数
6.反射的作用–绕过编译阶段为集合添加数据
  • 反射是作用在运行时的技术,此时集合的泛型将不能产生约束了,此时是可以为集合存入其他任意类型的元素的
  • 泛型只是在编译阶段可以约束集合只能操作某种数据类型,在编译成Class文件进入运行阶段时,其真实类型都是ArrayList了,泛型被擦除
7.反射的作用
  • 可以在运行时得到一个类的全部成分然后操作
  • 可以破坏封装性(private)(很突出)
  • 可以破坏泛型的约束性(很突出)
  • 更重要的用途是适合做Java高级框架
8.注解(Annotation)
  • 对Java中类、方法、成员变量做标记,然后进行特殊处理

自定义注解—格式

public @interface 注解名称{
	public 属性类型 属性名() default 默认值;
}

特殊属性:

  • value属性,如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写
  • 但是如果有多个属性,且多个属性没有默认值,那么value名称是不能省略的

元注解:

  • @Target:约束自定义注解只能在哪些地方使用(比如只能在方法使用)
  • @Retention:申明注解的生命周期
@Target(ElementType.METHOD, ELementType.FIELD)
public @interface MyTest{
}

@Target可使用的值定义在ElementType枚举类中,常用值如下:

  • Type:类、接口
  • FIELD:成员变量
  • METHOD:成员方法
  • PARAMETER:方法参数
  • CONSTRUCTOR:构造器
  • LOCAL_VARIABLE:局部变量

@Retention可使用的值定义在RetentionPolicy枚举类中,常用值如下:

  • SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在
  • CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值
  • RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段 (开发常用)
9.注解的解析
  • 判断注解是否存在,存在注解就解析出内容

与注解解析相关的接口:

  • Annotation:注解的顶级接口,注解都是Annotation类型的对象
  • AnnotatedElement:该接口定义了与注解解析相关的解析方法
方法说明
Annotation[ ] getDeclaredAnnotations()获得当前对象上使用的所有注解,返回注解数组
T getDeclaredAnnotation(Class< T> annotationClass)根据注解类型获得对应注解对象
boolean isAnnotationPresent(Class< Annotation> annotationClass)判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false

解析注解的技巧:

  • 注解在哪个成分上,我们就要先拿哪个成分对象
  • 成员方法:先获得该成员方法对应的Method对象,再拿上面的注解
10.动态代理

如何创建代理对象:

  • Java中代理的代表类是:java.lang.reflect.Proxy
  • Proxy提供了一个静态方法,用于为对象产生一个代理对象返回
public static Object newProxyInstance(ClassLoader loader, Class<?>[ ] interfaces, InvocationHandler h)
为对象返回一个代理对象
参数一:定义代理类的类加载器
参数二:代理类要实现的接口列表
参数三:将方法调用分派到的处理程序(代理对象的核心处理程序)

下面是为一个实现Skill接口的Star类的代理类StarAgentProxy

public class StarAgentProxy{
	public static Skill getProxy(Star obj){
		return (Skill) Proxy.newProxyInstance(obj.getClass().getClassLoader(),
						obj.getClass().getInterfaces(), new InvocationHandler(){
							@Override
							public Object invoke(Object proxy, Method method, Object[ ] args) throws Exception{
									System.out.println("收首付款");  //代理做的
									Object rs = method.invoke(obj, args);  //真正对象做的
									System.out.println("收尾款,把明星接回来"); //代理做的
									return rs;
									}
							});
	}

前两个参数都是固定的,第三个需要自己重写,代理类也都实现了原始类的接口,因为想要调用原始类的方法时都得通过代理类进行

在这里插入图片描述
实现动态代理:

  • 必须存在接口
  • 被代理对象需要实现接口
  • 使用Proxy类提供的方法,得到对象的代理对象

当左右方法前面需要干的事情和后面需要干的事情一致时,我们可以考虑使用代理,例如测试每个方法的运行时间。而且可扩展性超级强,之后原对象里再添加方法,可以直接走代理

11.动态代理的优点
  • 可以在不改变方法源码的情况下,实现对方法功能的增强,提高了代码的复用
  • 简化了编程工作,提高了开发效率,以高了软件系统的可扩展性
  • 可以为被代理对象的所有方法做代理
  • 非常灵活,支持任意接口类型的实现类对象做代理(将Skill类型改成泛型< T>,也可以为接口本身做代理
12.XML

XML特点和使用场景:

  • 一是纯文本,默认使用UTF-8;二是可嵌套
  • 使用场景:XML内容经常被当成消息进行网络传输,或者作为配置文件用于存储系统的信息

XML的语法规则

  • 文档声明必须是第一行
<?xml version="1.0" encoding="UTF-8" ?>
version:XML默认的版本号码
encoding:本XML文件的编码

XML的标签(元素)规则

  • 标签由一对尖括号和合法标识符组成:< name>< /name>,必须存在一个根标签,有且只能有一个
  • 标签必须成对出现,有开始,有结束
  • 特殊的标签可以不成对,但是必须有结束标记,如:< br/>
  • 标签中可以定义属性,属性和标签名空格隔开,属性值必须用引号引起来< student id=“1”>< /student>

XML的其他组成

  • XML文件中可以定义注释信息:< !-- 注释内容 -->
  • XML文件中可以存在以下特殊字符
&lt; < 小于
&gt; > 大于
&amp; & 和号
&apos; ' 单引号
&quot; " 引号
  • XML文件中可以存在CDATA区:<![CDATA[ ...内容... ]]>(里面的内容可以随便写,不用担心冲突)
13.文档约束
  • 用来限定xml文件中的标签以及属性应该怎么写。
  • 分类:DTD和schema

DTD

  • 可以约束格式,但不能约束数据类型

schema

  • 可以约束具体的数据类型,约束能力上更强大
  • 后缀是.xsd(xml schema 约束)
14.XML解析技术
  • SAX解析:一行行解析,适合大文件
  • DOM解析(dom4j):将整个文件加载到内存,适合小文件

在这里插入图片描述
Dom解析的文档对象模型:

  • Document对象:整个xml文档
  • Element对象:标签
  • Attribute对象:属性
  • Text对象:文本内容
  • Element、Attribute、Text三者都是Node对象
15.Dom4j:用于解析数据

得到Document对象:

SAXReader类

方法说明
public SAXReader()创建Dom4J的解析器对象
Document read(String url)加载XML文件成为Document对象

Document类

方法说明
Element getRootElement()获取根元素对象

Dom4j解析XML的元素、属性、文本

方法名说明
List< Element> elements()得到当前元素下所有一级子元素
List< Element> elements(String name)得到当前元素下指定名字的子元素返回集合
Element element(String name)得到当前元素下指定名字的子元素,如果重名返回第一个
String getName()得到元素名字
String attributeValue(String name)通过属性名直接得到属性值
String elementText(子元素名)得到指定名称的子元素的文本
String getText()得到文本
16.XPath:进行信息检索

使用Xpath检索XML文件:

  • 导入jar包(dom4j和jaxen-1.1.2.jar),Xpath技术依赖Dom4j技术
  • 通过dom4j的SAXReader获取Document对象
  • 利用Xpath提供的API,结合XPath的语法完成选取XML文档元素进行节点解析操作
  • Document中与Xpath相关的API如下:
方法名说明
Node selectSingleNode(“表达式”)获取符合表达式的唯一元素
List< Node> selectNodes(“表达式”)获取符合表达式的元素集合

XPath:绝对路径

  • 采用绝对路径获取从根节点开始逐层的查找
方法名说明
/根元素/子元素/孙元素从根元素开始,一级一级向下查找,不能跨级

XPath:相对路径

  • 先得到根节点,在采用相对路径一级一级向下查找
方法名说明
./子元素/孙元素从当前元素开始,一级一级向下查找,不能跨级

XPath:全文搜索

  • 直接全文搜索所有的name元素并打印
方法名说明
//name找名称为name的元素,无论元素在哪里
//contact/name找contact,无论在哪一级,但name一定是contact的子节点
//contact//namecontact无论在哪一种,name只要是contact的子孙元素都可以找到

XPath:属性查找

  • 在全文中搜索属性,或者带属性的元素
方法名说明
//@属性名查找属性对象,无论是哪个元素,只要有这个属性即可
//元素[@属性名]查找元素对象,全文搜索指定元素名和属性名
//元素[@属性名=‘值’]查找元素对象,全文搜索指定元素名和属性名,并且属性值相等
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java.lang.NoClassDefFoundError: org/jaxen/JaxenException at org.dom4j.DocumentFactory.createXPath(DocumentFactory.java:230) at org.dom4j.tree.AbstractNode.createXPath(AbstractNode.java:207) at org.dom4j.tree.AbstractNode.selectSingleNode(AbstractNode.java:183) at demo.TestXML.getTaskByName(TestXML.java:19) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunne
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值