第一节:反射(Reflection)
2.1 为什么使用反射
需求: 我公司定义了一组接口,然后第三方公司按照我公司的接口实现了一套功能,然后交给我们,但是我们公司的项目已经结束,如何实现动态加载第三方公司提供的功能。
2.2 什么是反射
反射就是把Java类中的各种成分映射成一个个的Java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。
2.3 反射常用类
Class类—可获取类和类的成员信息
Field类—可访问类的属性
Method类—可调用类的方法
Constructor类—可调用类的构造方法
2.4 使用反射的基本步骤
1.导入java.lang.reflect.*
2.获得需要操作的类的Java.lang.Class对象
3.调用Class的方法获取Field、Method等对象
4.使用反射API进行操作(设置属性﹑调用方法)
第二节:Class类
2.1 Class类是反射机制的起源和入口
每个类都有自己的Class对象
提供了获取类信息的相关方法
Class类继承自Object类
2.2 Class类存放类的结构信息
类名
父类﹑接口
方法﹑构造方法﹑属性
注释
2.3 获取 Class对象的方式
第一种方式
//方法1:对象.getClass() Student stu=new Student(); Class clazz=stu.getClass();
第二种方式
//方法2:类.class clazz= Student.class; clazz=String.class;
第三种方式(推荐)
//方法3:Class.forName() clazz=Class.forName("java.lang.String"); clazz=Class.forName("java.util.Date");
2.4 获取类的其他结构信息
Class clazz = Class.forName("java.lang.Object"); Field fields[ ] = clazz.getDeclaredFields();//获取Field 对象 Method methods[] = clazz.getDeclaredMethods();//获取Method 对象 Constructor constructors[] = clazz.getDeclaredConstructors();//获取Constructor对象
示例:
public class Person {
//成员变量
private String name;
private int age;
private String gender;
//构造方法
public Person() {
}
public Person(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
//方法
//无参无返回值
public void show(){
System.out.println("姓名:"+name+" 年龄:"+age+" 性别:"+gender);
}
//有参无返回值
public void show(String address){
System.out.println("姓名:"+name+" 年龄:"+age+" 性别:"+gender+" 地址:"+address);
}
//带返回值的方法
public String getInfo(){
return "信息:"+name+" "+age+" "+gender;
}
//静态方法
public static void print(){
System.out.println("这是一个静态方法");
}
//私有方法
private void show(String address,String email){
System.out.println("地址:"+address+" 邮箱:"+email);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
使用反射获取Person类中的信息:
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Demo {
public static void main(String[] args)throws Exception {
// getClazz();
//getConstructor();
//getMethed();
getField();
}
//获取类的类对象
public static void getClazz()throws Exception{
//使用class属性获
Class clazz1 = Person.class;
System.out.println(clazz1.hashCode());
//使用getClass
Person person=new Person();
Class > clazz2 = person.getClass();
System.out.println(clazz2.hashCode());
//使用 Class.forName方法 耦合性低 不依赖于具体的类 可编译通过
Class> clazz3=Class.forName("com.vince.practice04.Fanshe.fanshe01.Person");
System.out.println(clazz3.hashCode());
}
public static void getConstructor()throws Exception{
Class> clazz= Class.forName("com.vince.practice04.Fanshe.fanshe01.Person");
//获取构造方法
Constructor>[] constructors = clazz.getConstructors();
for (Constructor> constructor : constructors) {
System.out.println(constructor);
}
Constructor> constructor = clazz.getConstructor(); //获取单个无参
//获取带参
Constructor> constructor1 = clazz.getConstructor(String.class, int.class, String.class);
//创建对象
System.out.println("-----------------------");
Object o = constructor.newInstance();
System.out.println(o);
Object o1 = constructor1.newInstance("zhagnsan ", 23, "nan");
System.out.println(o1);
}
//获取方法
public static void getMethed()throws Exception{
Class> clazz = Class.forName("com.vince.practice04.Fanshe.fanshe01.Person");
/* //
Method[] methods = clazz.getMethods(); // 获取类自己的所有公共方法 继承D的公开方法
for (Method method : methods) {
System.out.println(method);
}
clazz.getDeclaredMethods // 获取类自己的公开方法和非公开的方法
*/
// 获取带参方法
Constructor> constructor1 = clazz.getConstructor(String.class, int.class, String.class);
Object zhangsan1 = constructor1.newInstance("张三",13,"男");
Method method = clazz.getMethod("show", String.class);
method.invoke(zhangsan1,"北京");
System.out.println("-------------带返回值的方法---------------");
Method getInfo = clazz.getMethod("getInfo");
Object value = getInfo.invoke(zhangsan1);
System.out.println(value);
System.out.println("----------获取私有方法--------------");
//获取私有方法
Constructor> constructor = clazz.getConstructor(String.class, int.class, String.class);
Object zhangsan = constructor.newInstance("张三",13,"男");
Method method1 = clazz.getDeclaredMethod("show", String.class, String.class);
method1.setAccessible(true); // 设置访问权限无效。
method1.invoke(zhangsan,"北京","[email protected]");
System.out.println("------------获取静态方法------------");
Method print = clazz.getMethod("print");
print.invoke(null);
}
//获取字段。
public static void getField()throws Exception{
Class> clazz = Class.forName("com.vince.practice04.Fanshe.fanshe01.Person");
Field[] fields = clazz.getDeclaredFields(); //获取多个字段
for (Field field : fields) {
System.out.println(field);
}
System.out.println("------------获取单个字段--------------");
Field name = clazz.getDeclaredField("name");
//创建对象
Object lixin = clazz.newInstance();
//赋值
name.setAccessible(true); //设置访问权限无效
name.set(lixin, "李欣");
//获取
Object object = name.get(lixin);
System.out.println(object);
}
}
第三节:反射技术的优点和缺点
优点:
1.提高了Java程序的灵活性和扩展性,降低了耦合性,提高自适应能力
2.允许程序创建和控制任何类的对象,无需提前硬编码目标类
缺点:
1.性能问题
2.代码维护问题
第四节:注解
什么是注解
Annotation其实就是代码里的特殊标记, 它用于替代配置文件,也就是说,传统方式通过配置文件告诉类如何运行,有了注解技术后,开发人员可以通过注解告诉类如何运行。在Java技术里注解的典型应用是:可以通过反射技术去得到类里面的注解,以决定怎么去运行类。
三个基本的 Annotation:
@Override:限定重写父类方法, 该注解只能用于方法
@Deprecated:用于表示某个程序元素(类, 方法等)已过时
@SuppressWarnings: 抑制编译器警告.
2.1 自定义注解:
定义新的 Annotation 类型使用@interface关键字
声明注解的属性
注解属性的作用:原来写在配置文件中的信息,可以通过注解的属性进行描述。 Annotation的属性声明方式: public String name(); public可以不写。 属性默认值声明方式:Stringname() default “xxx”; 特殊属性value:如果注解中有一个名称value的属性,那么使用注解时可以省略value=部分,如@MyAnnotation(“xxx") 特殊属性value[];
注解属性的类型可以是: String类型 基本数据类型 Class类型 枚举类型 注解类型 以上类型的一维数组
2.2 JDK的元 Annotation
@ RetentionPolicy.CLASS: 编译器将把注解记录在 class文件中. 当运行 Java 程序时, JVM 不会保留注解. 这是默认值
@Target:指定注解用于修饰类的哪个成员.@Target 包含了一个名为value,类型为ElementType的成员变量。
@Documented:用于指定被该元 Annotation 修饰的Annotation类将被 javadoc 工具提取成文档。
@Inherited:被它修饰的 Annotation 将具有继承性.如果某个类使用了被 @Inherited 修饰的Annotation,则其子类将自动具有该注解。
自定义注解:
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Inherited
public @interface StudentAnnotation {
String name();
int age();
String gender();
}
使用:
import java.lang.reflect.Method;
@StudentAnnotation(name="lisi",age=26,gender = "男")
public class Student {
@StudentAnnotation(name="张三",age=26,gender = "男")
public void show()throws Exception{
//获取方法上面的注解
Class> clazz = Class.forName("com.vince.practice04.Fanshe.Zhujie.zhijie1.Student");
//获取方法
Method show = clazz.getMethod("show");
// 获取方法上面的注解
StudentAnnotation annotation = show.getAnnotation(StudentAnnotation.class);
//获取注解属性
String name = annotation.name();
int age = annotation.age();
String gender = annotation.gender();
System.out.println("学生信息:"+name+" "+age+" "+gender);
}
}
测试:
public class Test {
public static void main(String[] args)throws Exception {
Student stu=new Student();
stu.show();
}
}
第五节:XML语言
5.1为什么使用XML
问题1:Windows系统的应用怎么和Linux系统中的应用交互数据
问题2:其它诸如此类跨平台、跨操作系统的数据交互问题……
使用XML解决。
5.2XML概述
可扩展性标记语言(eXtensible Markup Language),文件扩展名.xml
用途:描述、传输数据
使用场合:
◦持久化存储数据
◦数据交换
◦数据配置
第六节:XML解析
XML解析方式
1 DOM解析 2 SAX解析
DOM和SAX比较 :
DOM解析 (Document Object Model) 文档对象模型
易用性强,使用DOM时,将把所有的XML文档信息都存于内存中,并且遍历简单,支持XPath,增强了易用性。
效率低,解析速度慢,内存占用量过高,对于大文件来说几乎不可能使用
支持增删改查
SAX解析(Simple API for Xml)
SAX是一个用于处理XML事件驱动的“推”模型,虽然它不是W3C标准,但它却是一个得到了广泛认可的API
SAX模型最大的优点是内存消耗小
只适合读取。
使用Dom解析:
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.List;
public class Demo01 {
public static void main(String[] args) throws Exception{
// 1 创建SaxReader读取器
SAXReader reader = new SAXReader();
// 2 读取 返回document 对象(Dom树)
Document document = reader.read(new FileReader("books.xml"));
// 3
Element root = document.getRootElement();
// 4 获取子节点
List booklist = root.elements("book");
// 5 遍历
for (Element element : booklist) {
//获取属性
String id=element.attributeValue("id");
String name=element.elementText("name");
String sex=element.elementText("sex");
System.out.println(id+name+sex);
}
// 6 添加节点
Element newbook = root.addElement("book");
// 添加属性
newbook.addAttribute("id", "1004");
newbook.addElement("name").setText("手机开发");
newbook.addElement("sex").setText("男");
newbook.addElement("price").setText("1009");
//写入
OutputFormat format= OutputFormat.createPrettyPrint();//创建一个漂亮的输出格式
format.setEncoding("utf-8");
XMLWriter writer=new XMLWriter(new FileWriter("src\\books.xml"), format);
//XMLWriter writer=new XMLWriter(new FileWriter("src\\books2.xml"), format);
writer.write(document);
writer.close();
System.out.println("写入成功1");
}
}