实训笔记6.21

6.21

一、座右铭

我的故事你说,我的文字我落,我值几两你定,我去何方我挑。

二、知识回顾

2.1 JavaIO流

2.1.1 从三个角度分为六类

  1. 输入流和输出流
  2. 字节流和字符流
  3. 节点流和功能流

2.1.2 IO流的四大抽象基类

四大抽象基类
InputStream
OutputStream
Reader
Writer

InputStream、OutputStream:

所有格式的数据

Reader、Writer:

因为涉及到字符编码的转换,因此只能处理纯文本类型的数据。

2.1.3 IO流的常用类

2.1.3.1 节点流
2.1.3.1.1 数组流:
  1. ByteArrayInputStream
  2. ByteArrayOutputStream
  3. CharArrayReader
  4. CharArrayWriter
2.1.3.1.2 文件流:
  1. FileInputStream
  2. FileOutputStream
  3. FileWriter
  4. FileReader
  5. File文件对象类
2.1.3.2 功能流
2.1.3.2.1 缓冲流:
  1. BufferedInputStream
  2. BufferedOutputStream
  3. BufferedReader
  4. BufferedWriter
2.1.3.2.2 转换流:
  1. InputStreamReader
  2. OutputStreamWriter
2.1.3.2.3 对象流:
  1. ObjectInputStream

  2. ObjectOutputStream

  3. 序列化和反序列化

  4. 两个让Java类具备序列化和反序列化能力的接口

    1. Serializable:static、transient

    2. Externalizable:两个重写方法自己指定哪些需要序列化

      主要就是指定Java中哪些属性值可以被序列化,哪些不能被序列化

    3. 任何一个可以被序列化的类都具备一个序列化版本ID

2.1.3.2.4 打印流:
  1. PrintStream
  2. PrintWriter
2.1.3.2.5 标准输入和标准输出流:
  1. System.in
  2. System.out

2.2 Java注解

注解是给Java程序进行解释说明或者是在Java的编译期间、运行期间提供一些特殊的“服务”

注解的声明

@元注解 访问控制修饰符 @interface 注解名{ 属性类型 属性名() default 默认值; }

元注解–四个

注解名称
@Target
@Retention
@Documented
@Inherited

2.3 注解的应用–Lombok

帮助我们基于注解快速生成一个JavaBean类,借助几个SOURCE声明周期的注解,在Java编译时期将JavaBean有关的内容给我们生成到.class文件当中

注解名称 包含注解
@Data @ToString @Getter @Setter @EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@Builder

三、Java反射(reflect)机制

反射是在Java运行期间,可以获取类中任何一块组成,以及可以调用或者运行类中任何一块内容

3.1 反射的作用主要有两个:

  1. 运行期间获取类中的任何一种成分:注解、方法、属性、构造器等等
  2. 不用自己手动构建该类对象,也可以调用执行这个类中所有的内容

3.2 反射的核心机制–Class类

Class类是Java中所有类的类。Java中所有的类。都是Class类的一个实例对象

在Java当中,任何一个类一旦加载到JVM内存当中,那么我们就会把这个类创建称为Class类的一个实例对象,然后使用这个类的时候,JVM会通过Class的实例对象去看在这个类当中有没有我们调用的属性和方法。

通过Class类就可以获取任何一个类当中声明的任何一种成分,同时还可以调用这些成

3.3 反射

反射第一步:获取该类的运行时类对象–获取该类的Class实例对象

任何一个类的Class实例对象,我们自己是无法创建的,他们都是在JVM内存加载的时候,由JVM内存自动创建的,在内存中仅且只有一份。因此我们只能获取,不能创建

3.3.1 获取该类的Class实例对象:

  1. 对象名.getClass():Class
  2. 类名.class:Class
  3. Class.forName(“全限定类名”):Class

同一个Class实例

代码示例:

		ArrayList<String> list = new ArrayList<>();
		//1、通过某个类的对象名.getClass()方法可以获取该类的class实列对象
		Class < ? extends ArrayList >  class1 = list.getClass();
		//2、通过类名.class去获取该类的运行时类
		Class<ArrayList> class2 = ArrayList. class;
		//3、通过Class.forName(全限定类名)
		Class<?> class3 = Class.forName("java.util.ArrayList");
		System.out.println(class1==class2);//true
		System.out.println(class2==class3);//true

3.3.2 反射的作用一

反射的作用一:通过Class类获取类中的任何一个成分

  1. 获取类中的属性
  2. 获取类中的方法
  3. 获取类中的构造器
  4. 获取类上声明的注解

代码示例

Class<Student> cls = Student.class;
		Field field = cls.getField("phone");
		System.out.println(field.getModifiers());//1
		System.out.println(field.getName());//phone
		System.out.println(field.getType());//class java.lang.String
		
		Field[] fields = cls.getFields();
		
		Field field2 = cls.getDeclaredField("name");
		System.out.println(field2);//private java.lang.String com.sxuek.study.Student.name
		
		Field[] declaredFields = cls.getDeclaredFields();
		for(Field f : declaredFields) {
    
    
			System.out.println(f);
			//private java.lang.String com.sxuek.study.Student.name
			//protected java.lang.Integer com.sxuek.study.Student.age
			//java.lang.String com.sxuek.study.Student.sex
			//public java.lang.String com.sxuek.study.Student.phone
		}
Class<Student> cls = Student.class;
		Method[] methods = cls.getDeclaredMethods();
		for(Method method:methods) {
    
    
			System.out.println(method.getModifiers());//2
			System.out.println(method.getName());//run
			System.out.println(method.getReturnType());//void
			Parameter[] parameters = method.getParameters();
			for(Parameter p : parameters) {
    
    
				System.out.println(p.getType());//4  int  0 void  class java.lang.String  1  int  int  int
				System.out.println(p.getName());//sum call   arg0  diff  arg0  arg1
			}
		}
		
		Constructor<Student> constructor = cls.getConstructor(String.class,Integer.class);

3.3.2 反射的作用二

反射的作用二:通过反射调用类中的成分

  1. 通过反射获取的构造器创建该类的对象
  2. 通过反射获得的属性去设置或者获取属性的值
  3. 通过反射获得的方法去调用方法执行
  4. 通过反射只能获取RUNTIME周期的注解

代码示例:

Class<Student> clz = Student.class;
		Constructor<Student> constructor = clz.getDeclaredConstructor(String.class,Integer.class);
		constructor.setAccessible(true);
		/**
		 * 可以根据获取的构造器创建这个类的对象
		 */
		Student student = constructor.newInstance("zs",20);
		System.out.println(student);//Student [name=zs, age=20, sex=null, phone=null]
		
		Field field = clz.getDeclaredField("name");
		field.setAccessible(true);
		Object object = field.get(student);
		System.out.println(object);//zs
		
		field.set(student,"ls");
		System.out.println(student.getName());//ls
		
		Method method = clz.getDeclaredMethod("diff",int.class,int.class);
		method.setAccessible(true);
		Object value = method.invoke(student, 2,1);
		System.out.println(value);//1
package com.sxuek.study.reflectdemo;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class ObjectGen {
    
    
	public static void main(String[] args) {
    
    
		Teacher teacher = genObject(Teacher.class);
		System.out.println(teacher);//null
		
		Book book = genObject(Book.class);
		System.out.println(book);//Book(bookName=流浪地球, author=刘慈欣, publisher=淘票票, price=39)
	}
	
	
	public static <T> T genObject(Class<T> cls) {
    
    
		//1、获取这个类上声明的注解值--
		MyAnno annotation = cls.getDeclaredAnnotation(MyAnno.class);
		//文件的路径
		String value = annotation.value();
		
		//2、根据IO流读取文件数据获取配置项的值
		Map<String, Object> map = new HashMap<>();
		BufferedReader br = null;
		try {
    
    
			br = new BufferedReader(new FileReader(value));
			String line = null;
			while((line = br.readLine()) != null) {
    
    
				String[] array = line.split("=");
				map.put(array[0], array[1]);
			}
			//3、根据反射获取类中构造器,构建对象
//			T newInstance = cls.newInstance();//调用的是无参构造器 无参构造器必须存在,而且必须是public
			Constructor<T> constructor = cls.getDeclaredConstructor();
			constructor.setAccessible(true);
			T t = constructor.newInstance();
			//4、根据反射去获取类中的属性,然后结合构建的对象以及读取的文件中的数据给对应的属性赋值
			Field[] fields = cls.getDeclaredFields();
			for(Field f : fields) {
    
    
				//5、属性赋值时 读取属性上的注解值,然后根据属性的注解值去配置文件获取对应的值给属性赋值
				MyAnno anno = f.getDeclaredAnnotation(MyAnno.class);
				String value2 = anno.value();
				f.setAccessible(true);
				f.set(t, map.get(value2));
			}
			return t;
		} catch (Exception e) {
    
    
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
    
    
			if(br != null) {
    
    
				try {
    
    
					br.close();
				} catch (IOException e) {
    
    
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return null;
	}
}

猜你喜欢

转载自blog.csdn.net/cai_4/article/details/131334674
今日推荐