标签:trace return read static 用户 处理对象 oca center ace
反射机制是指在程序运行过程中,对任意一个类都能获取其所有属性和方法,并且对任意一个对象都能调用其任意一个方法。这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。
Java的反射API主要用于在运行过程中动态生成类,接口或对象等信息。
1、使用Class类的forName静态方法。如:
Class clazz = Class.forName("java.lang.String");
2、使用类的.class语法。如:
Class clazz = String.class;
3、使用对象的getClass()方法。如:
String str = "aa";
Class clazz = str.getClass();
1、使用Class对象的newInstance方法创建该Class对象对应类的实例(这种方法要求Class对象对应的类有默认的空构造器)。
Class clazz = Class.forName("java.lang.String");
Object obj = clazz.newInstance();
2、先使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance方法创建Class对象对应类的实例,这种方法可以选定构造方法创建实例。
Class clazz = Class.forName("com.jzq.reflect.Person"); Constructor constructor = clazz.getDeclaredConstructor(String.class,String.class);//获取指定参数构造方法创建对象 Person person = (Person) constructor.newInstance("李四",“男”);
在运行的代码中通过调用Method的invoke方法实现动态调用,比如动态传入参数及将方法参数化。
代码如下:
(1)定义Person类:
package com.jzq.foundation.reflect; public class Person { private String name; private String sex; public Person() { } public Person(String name, String sex) { this.name = name; this.sex = sex; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } @Override public String toString() { return "Person{" + "name=‘" + name + ‘\‘‘ + ", sex=‘" + sex + ‘\‘‘ + ‘}‘; } public void setSex(String sex) { this.sex = sex; } }
(2)调用invoke方法:
public class Main { public static void main(String[] args) { try { //获取Person类的Class对象 Class clazz = Class.forName("com.jzq.foundation.reflect.Person"); //获取Class对象中的setName方法 Method method = clazz.getMethod("setName", String.class); Constructor constructor = clazz.getConstructor(); Object obj = constructor.newInstance(); //动态调用obj对象的setName方法并传入王五参数 method.invoke(obj, "王五"); System.out.println(obj.toString()); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }
结果:
Person{name=‘王五‘, sex=‘null‘}
注解是一个接口,程序可以通过反射获取指定程序中元素的注解对象,然后通过该注解对象获取注解中的元数据信息。
2.2 元注解(定义在java.lang.annotation中)
@Target的取值类型如表:
名称 | 修饰目标 |
TYPE |
用于描述类、接口(包括注解类型)、枚举、 |
FIELD |
用于描述域 |
METHOD |
用于描述方法 |
PARAMETER |
用于描述参数 |
CONSTRUCTOR |
用于描述构造器 |
LOCAL_VARIABLE |
用于描述局部变量 |
ANNOTATION_TYPE |
用于描述一个注解 |
PACKAGE |
用于描述包 |
TYPE_PARAMETER |
对普通变量的声明 |
TYPE_USE |
能标注任何类型的名称 |
从 Java 7 开始,额外添加了 3 个注解:
1、定义注解接口:
import java.lang.annotation.*; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FruitProvider { //供应商编号 public int id() default -1; //供应商名称 public String name() default ""; //供应商地址 public String address() default ""; }
2、使用注解接口,定义Apple类,通过注解方式定义一个FruitProvider:
public class Apple { @FruitProvider(id=1,name="西安香蕉厂",address = "陕西省") private String appleProvider; public String getAppleProvider() { return appleProvider; } public void setAppleProvider(String appleProvider) { this.appleProvider = appleProvider; } }
3、定义FruitInfoUtil注解处理器,通过反射获取注解数据:
import java.lang.reflect.Field; public class FruitInfoUtil { public static void getFruitInfo(Class<?> clazz) { String strFruitPrivoder; Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { FruitProvider fruitProvider = (FruitProvider)field.getAnnotation(FruitProvider.class); strFruitPrivoder = "供应商编号: "+fruitProvider.id()+"供应商名称: "+fruitProvider.name() +"供应商地址: "+fruitProvider.address(); System.out.println(strFruitPrivoder); } } }
4、调用注解处理器使用:
public class Main { public static void main(String[] args) { FruitInfoUtil.getFruitInfo(Apple.class); } }
泛型提供了编译时类型的安全检测机制,该机制允许程序在编译时检测非法的类型。
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
注:在不使用泛型的情况下,引用Object类型也可以实现参数任意化,但强制类型转换必须明确知道实际参数的引用类型,不然可能会引起前置类型转换错误,在编译期无法识别这种错误,只能在运行期检测这种错误。
泛型标记 | 说明 |
E(Element) | 在集合中使用,表示在集合中存放的元素 |
T(Type) | 表示Java类,包括基础类和自定义类 |
K(key) | 表示键 |
V(value) | 表示值 |
N(Number) | 表示数值类型 |
? | 表示不确定的Java类型 |
类型通配符使用“?”表示所有具体的参数类型,如:List<?>在逻辑上是List<String>、List<Integer>等所有List<具体类型参数>的父类。
泛型方法是指方法的参数类型定义为泛型,以便在调用时接收不同类型的参数。在方法的内部根据传递给泛型方法的不同参数类型执行不同的处理方法。
具体用法如下:
public class GeneralClass { public static void main(String[] args) { generalMethod("Hello",3,new Worker()); } public static <T> void generalMethod(T ... inputArray){ for(T element:inputArray){ if(element instanceof Integer){ System.out.println("处理Integer类型数据"); }else if(element instanceof String){ System.out.println("处理String类型数据"); }else if(element instanceof Double){ System.out.println("处理Double类型数据"); }else if(element instanceof Float){ System.out.println("处理Float类型数据"); }else if(element instanceof Long){ System.out.println("处理Long类型数据"); }else if(element instanceof Boolean){ System.out.println("处理Boolean类型数据"); }else if(element instanceof Date){ System.out.println("处理Date类型数据"); }else if(element instanceof Worker){ //自定义Worker类 System.out.println("处理Worker类型数据"); } } } }
泛型类是指定义类时在类上定义泛型,以便类在使用时可以根据传入的不同参数类型实例化不同对象。
具体用法如下:
1、定义GeneralClass泛型类:
public class GeneralClass<T> { private T t; public T getT() { return t; } public void add(T t){ this.t = t; } }
2、使用GeneralClass泛型类:
public class Main { public static void main(String[] args) { GeneralClass<Integer> generalInt = new GeneralClass<Integer>(); generalInt.add(1); System.out.println(generalInt); GeneralClass<String> generalStr = new GeneralClass<String>(); generalStr.add("jksadhklja"); System.out.println(generalStr); } }
结果:
GeneralClass{t=1}
GeneralClass{t=jksadhklja}
泛型接口的声明与泛型类的声明类似,泛型接口的具体类型一般在实现类中进行声明,不同类型的实现类处理不同的业务逻辑。、
具体代码实现:
1、定义一个泛型接口:
public interface GeneralInterface<T> { public T getId(); }
2、定义泛型接口的实现类:
public class GeneralInterfaceImpl implements GeneralInterface<Integer> { public Integer getId() { Random random = new Random(1); return random.nextInt(); } }
3、使用泛型实现类:
public class Main { public static void main(String[] args) { GeneralInterfaceImpl generalInterface = new GeneralInterfaceImpl(); System.out.println(generalInterface.getId()); } }
类型檫除:在编码阶段采用泛型时加上的类型参数,会被编译器在编译时去掉。
泛型主要用于编译阶段,在编译后生成的Java字节代码文件中不包含泛型中的类型信息。如,编码时定义的List<Integer>在经过编译后同一为List。
Java类型檫除过程:
序列化:将一个对象及其状态信息保存到一个字节数组中。在需要时再将这些字节数组反序列化为对象。
Java序列化API为处理对象序列化提供了一个标准机制,应注意以下事项:
具体代码实现如下:
import java.io.Serializable; public class Worker implements Serializable { private static final long serialVersionUID = 123456789L; //name将被序列化 private String name; //transient修饰的变量不会被序列化 private transient int salary; //静态变量不会被序列化 static int age = 100; public String getName() { return name; } public void setName(String name) { this.name = name; } }
序列化框架:fastjson
具体代码如下:
public class Main { public static void main(String[] args) throws Exception{ //序列化数据到磁盘 FileOutputStream fos = new FileOutputStream("worker.out"); ObjectOutputStream oos = new ObjectOutputStream(fos); Worker testObject = new Worker(); testObject.setName("jzq"); oos.writeObject(testObject); oos.flush(); oos.close(); //反序列化并解析数据状态 FileInputStream fis = new FileInputStream("worker.out"); ObjectInputStream ois = new ObjectInputStream(fis); Worker deTest = (Worker)ois.readObject(); System.out.println(deTest.getName()); } }
标签:trace return read static 用户 处理对象 oca center ace
原文地址:https://www.cnblogs.com/strong-FE/p/12171167.html