反射
类加载器
类加载
当程序要使用某个类时,如果该类还没有加载到内存中,则系统会通过类的加载、类的连接、类的初始化这三个步骤来对类进行初始化。如果不出现意外情况,JVM将连续完成这三个步骤,所以有时也把这三个步骤统称为类加载或类初始化。
类的加载器的作用
- 就是指将class文件读入内存,并为之创建一个java.lang.Class对象
- 任何类被使用时,系统都会为之建立一个java.lang.Class对象
JVM的类加载机制
- 全盘负责:
- 父类委托:
- 缓存机制:
类的连接
- 验证阶段:用于检验被加载的类是否有正确的内部结构,并和其他类协调一致
- 准备阶段:负责为类的类变量分配内存,并设置默认初始化值
- 解析阶段:将的类的二进制数据中的符号引用替换为直接引用
类的初始化
- 在该阶段,主要就是对类变量进行初始化
类初始化的步骤
- 假如类还未被加载和连接,则程序先加载并连接该类
- 假如该类的直接父类还未被初始化,则先初始化其直接父类
- 假如该类有初始化语句,则系统依次执行这些初始化语句
需要注意的是:在执行第二个步骤的时候,系统对直接父类的初始化步骤也遵循初始化步骤1-3
类的初始化时机/什么时候会触发类初始化
- 创建类的实例
- 调用类的类方法
- 访问类或者接口的类变量,或者为该类变量赋值
- 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
- 初始化某个类的子类
- 直接使用java.exe命令来运行某个主类
反射类
反射类的构造方法
反射类的字段
反射类的方法
JSON
JSON是一种数据格式,本质上是一个字符串。JSON是JavaScript对象的字符串表现形式,在JS中对象是用{}表示,数组使用[]表示。
let student = {age: 18,name: 'zs'}let fruits = ['apple', 'tomato', 'banana']
使用JSON-lib解析JSON
JSON 转对象
String json = "{age:18,name:'zs'}";JSONObject jsonObject = new JSONObject(json);int age = jsonObject.getInt("age");String name = jsonObject.getString("zs");Student student = new Student(age, name);System.out.println(student);
JSON转复杂对象
public static void main(String[] args) throws JSONException {String json = "{age:19,name:'ls',score:{java:10,php:20,database:40,c:58}}";JSONObject jsonObject = new JSONObject(json);int age = jsonObject.getInt("age");String name = jsonObject.getString("name");JSONObject score1 = jsonObject.getJSONObject("score");int java = score1.getInt("java");int php = score1.getInt("php");int database = score1.getInt("database");int c = score1.getInt("c");Score score = new Score(java, php, database, c);Student student = new Student(age, name, score);System.out.println(student);}
JSON转数组
public static void main(String[] args) throws JSONException {String json = "[{java:2,php:3,database:5,c:22},{java:3,php:5,database:6,c:26}]";JSONArray jsonArray = new JSONArray(json);List<Score> scoreList = new ArrayList<>();for (int i = 0; i < jsonArray.length(); i++) {JSONObject jsonObject = jsonArray.getJSONObject(i);int java = jsonObject.getInt("java");int php = jsonObject.getInt("php");int database = jsonObject.getInt("database");int c = jsonObject.getInt("c");scoreList.add(new Score(java, php, database, c));}System.out.println(scoreList);}
JSON转复杂数组对象
public static void main(String[] args) throws JSONException {String json = "[{age:2,name:'zs',score:{java:2,php:3,database:5,c:22}},{age:19,name:'ls',score:{java:3,php:5,database:6,c:26}}]";List<Student> studentList = new ArrayList<>();JSONArray jsonArray = new JSONArray(json);for (int i = 0; i < jsonArray.length(); i++) {JSONObject jsonObject = jsonArray.getJSONObject(i);int age = jsonObject.getInt("age");String name = jsonObject.getString("name");JSONObject scoreJsonObject = jsonObject.getJSONObject("score");int java = scoreJsonObject.getInt("java");int php = scoreJsonObject.getInt("php");int database = scoreJsonObject.getInt("database");int c = scoreJsonObject.getInt("c");studentList.add(new Student(age, name, new Score(java, php, database, c)));}System.out.println(studentList);}
对象转JSON
public static void main(String[] args) {Student student = new Student(19, "zs");JSONObject jsonObject = new JSONObject(student);System.out.println(jsonObject.toString());}
数组转JSON
public static void main(String[] args) {List<Student> studentList = new ArrayList<>();studentList.add(new Student(19, "za", new Score(1, 2, 3, 45)));studentList.add(new Student(12, "zc", new Score(12, 32, 23, 15)));studentList.add(new Student(13, "zg", new Score(13, 22, 23, 25)));studentList.add(new Student(15, "zc", new Score(15, 25, 23, 35)));JSONArray jsonArray = new JSONArray(studentList);System.out.println(jsonArray.toString());}
使用fastjson
public static void main(String[] args) {// 1. json -> 对象String json = "{age:18,name:'zs'}";Student student = JSON.parseObject(json, Student.class);System.out.println(student);// 2. json -> 对象String json1 = "{age:19,name:'ls',score:{java:10,php:20,database:40,c:58}}";Student student1 = JSON.parseObject(json1, Student.class);System.out.println(student1);// 3. json -> 对象数组String json2 = "[{java:2,php:3,database:5,c:22},{java:3,php:5,database:6,c:26}]";List student2 = JSON.parseArray(json2, Student.class);for (int i = 0; i < student2.size(); i++) {Object o = student2.get(i);System.out.println(o);}// 4. json -> 泛型对象数组String json3 = "[{age:2,name:'zs',score:{java:2,php:3,database:5,c:22}},{age:19,name:'ls',score:{java:3,php:5,database:6,c:26}}]";// Type typeToken = new TypeToken<ArrayList<Student>>(){}.getType();List<Student> studentList = JSON.parseArray(json3, Student.class);for (int i = 0; i < studentList.size(); i++) {System.out.println(studentList.get(i));}// 5. 普通对象 -> jsonStudent o = new Student(19, "zs");System.out.println(JSON.toJSONString(o));// 6. 数组对象 -> jsonList<Student> s1 = new ArrayList<>();s1.add(new Student(19, "za", new Score(1, 2, 3, 45)));s1.add(new Student(12, "zc", new Score(12, 32, 23, 15)));s1.add(new Student(13, "zg", new Score(13, 22, 23, 25)));s1.add(new Student(15, "zc", new Score(15, 25, 23, 35)));System.out.println(JSON.toJSONString(s1));}
使用gson
public static void main(String[] args) {// 1. json -> 对象String json = "{age:18,name:'zs'}";Gson gson = new Gson();Student student = gson.fromJson(json, Student.class);System.out.println(student);// 2. json -> 对象String json1 = "{age:19,name:'ls',score:{java:10,php:20,database:40,c:58}}";Student student1 = gson.fromJson(json1, Student.class);System.out.println(student1);// 3. json -> 对象数组String json2 = "[{java:2,php:3,database:5,c:22},{java:3,php:5,database:6,c:26}]";List student2 = gson.fromJson(json2, ArrayList.class);for (int i = 0; i < student2.size(); i++) {Object o = student2.get(i);System.out.println(o);}// 4. json -> 泛型对象数组String json3 = "[{age:2,name:'zs',score:{java:2,php:3,database:5,c:22}},{age:19,name:'ls',score:{java:3,php:5,database:6,c:26}}]";Type typeToken = new TypeToken<ArrayList<Student>>(){}.getType();List<Student> studentList = gson.fromJson(json3, typeToken);for (int i = 0; i < studentList.size(); i++) {System.out.println(studentList.get(i));}// 5. 普通对象 -> jsonStudent o = new Student(19, "zs");System.out.println(gson.toJson(o));// 6. 数组对象 -> jsonList<Student> s1 = new ArrayList<>();s1.add(new Student(19, "za", new Score(1, 2, 3, 45)));s1.add(new Student(12, "zc", new Score(12, 32, 23, 15)));s1.add(new Student(13, "zg", new Score(13, 22, 23, 25)));s1.add(new Student(15, "zc", new Score(15, 25, 23, 35)));System.out.println(gson.toJson(s1));}
实现一个简单的JSON解析工具
package com.shaw.json;import java.util.HashMap;import java.util.Map;import java.util.Objects;public class RabbitJSON {/* key-value 映射 key:属性 value:值 */private Map<String, String> map;/* 调式 */public Map<String, String> getMap() {return map;}public RabbitJSON() {this.map = new HashMap<>();}/**** @param JSONString JSON字符串*/public RabbitJSON(String JSONString) {this(new JSONCharParser(JSONString));}/**** @param jsonCharParser JSON字符解析器 com.shaw.json.JSONCharParser*/public RabbitJSON(JSONCharParser jsonCharParser) {this();// JSON对象字符串不是以'{'开头if (jsonCharParser.next() != '{') {throw new JSONSyntaxException("JSON对象字符串不是以 { 开头");}while (true) {char c = jsonCharParser.nextClean();// a// System.out.println(c);switch (c) {case '\u0000': // \u0000 Unicode 空白字符throw new JSONSyntaxException("JSON对象格式不正确,包含空格");case '}': // }:JSON语法结束标记return;default:// 回退jsonCharParser.back();// 读取对象的keyString key = jsonCharParser.nextValue().toString();System.out.println("key = " + key);// :c = jsonCharParser.nextClean();System.out.println("c = " + c);if (c != ':') {throw new JSONSyntaxException("JSON 语法错误,在附近" + key + c);}// 读取对象的valuethis.map.put(key, jsonCharParser.nextValue().toString());switch (jsonCharParser.nextClean()) {case ',':case ';':if (jsonCharParser.nextClean() == '}') {return;}jsonCharParser.back();break;case '}':return;default:throw new JSONSyntaxException("JSON语法错误");}}}}/*** JSON语法错误异常* @author Shaw*/private static class JSONSyntaxException extends IllegalArgumentException {public JSONSyntaxException() {super();}public JSONSyntaxException(String s) {super(s);}public JSONSyntaxException(String message, Throwable cause) {super(message, cause);}public JSONSyntaxException(Throwable cause) {super(cause);}}public Object get(String key) {Object value = this.map.get(key);return Objects.requireNonNull(value, "value 为 null");}public boolean getBoolean(String key) {Object value = this.get(key);if (value.equals(Boolean.TRUE) || ((value instanceof String) && ((String) value).equalsIgnoreCase("true"))) {return true;} else if (value.equals(Boolean.FALSE) || ((value instanceof String) && ((String) value).equalsIgnoreCase("false"))) {return false;} else {throw new JSONSyntaxException("值解析失败" + value);}// 不等于 Boolean.FALSE 并且也不是 String类型 或者 强转成String类型忽略大小写匹配不等于false// if (!value.equals(Boolean.FALSE) && (!(value instanceof String) || !((String) value).equalsIgnoreCase("false"))) {// if (!value.equals(Boolean.TRUE) && (!(value instanceof String) || !((String) value).equalsIgnoreCase("true"))) {// throw new JSONSyntaxException("值解析失败:" + value);// } else {// return false;// }// } else {// return false;// }}public double getDouble(String key) throws ClassCastException {Object value = this.get(key);return value instanceof Number ? ((Number) value).doubleValue() : Double.parseDouble((String) value);}public int getInt(String key) {Object value = this.get(key);return value instanceof Number ? ((Number) value).intValue() : Integer.parseInt((String) value);}public String getString(String key){return this.get(key).toString();}}
package com.shaw.json;import java.io.IOException;import java.io.Reader;import java.io.StringReader;public class JSONCharParser {/* 字符读取器 */private Reader reader;/* 是否到达结尾 */private boolean eof;/* 字符数量 */private int charCount;/* 行数 */private int lineCount;/* 索引 */private int index;/* 上一个字符 */private char previous;/* 是否有上一个字符 */private boolean hasPrevious;public JSONCharParser(String JSONString) {this(new StringReader(JSONString));this.eof = false;this.charCount = 0;this.lineCount = 0;this.index = 0;this.previous = 0;this.hasPrevious = false;}public JSONCharParser(Reader reader) {this.reader = reader;}/*** 获取JSON字符串中的下一个字符** @return 下一个字符 如果没有将返回 ASCII 对应的0 也就是空白字符*/public char next() {int c = -1;if (this.hasPrevious) {this.hasPrevious = false;c = this.previous;} else {try {// 读取下一个字符c = this.reader.read();} catch (IOException e) {e.printStackTrace();}// 到达文件结尾if (c < 0) {this.eof = true;c = 0;}}// 记录索引+1this.index++;// 换行符/** ASCII:* 0 空字符* 1 标题开始* 10 换行键* */if (c == '\r') {// 记录行数+1this.lineCount++;this.charCount = c == 10 ? 0 : 1;} else if (c == 10) {this.lineCount++;this.charCount = 0;} else {this.charCount++;}this.previous = (char) c;return this.previous;}/*** 获取非空白字符的下一个字符 不包括* 1. 空白字符* 2. 换行字符** @return 字符*/public char nextClean() {char c;do {c = this.next();} while (c != 0 && c <= ' ');return c;}/*** 回退*/public void back() {// if (this.hasPrevious && this.index > 0) {if (this.index > 0) {this.charCount--;this.index--;this.hasPrevious = true;this.eof = true;} else {throw new JSONException();}}private static class JSONException extends IllegalArgumentException {public JSONException() {super();}public JSONException(String s) {super(s);}public JSONException(String message, Throwable cause) {super(message, cause);}public JSONException(Throwable cause) {super(cause);}}/*** 返回JSON字符串的key或者value** @return 字符串的value 或者 对象的value*/public Object nextValue() {int c = this.nextClean();switch (c) {// key 已 " 或 '包含,例 'age'case '"':case '\'':// \'return this.nextString((char) c);// 对象case '{':this.back();// return new Object();break;// 其他情况 比如 {age:10} 不已 ' 或 " 包含default:StringBuilder sb = new StringBuilder();// :}]" 表示结束// ,;=# 表示非法字符// System.out.println("(char)c = " + (char) c);for (; c >= ' ' && ",:]}\\\";=#".indexOf(c) < 0; c = this.next()) {sb.append((char) c);}// System.out.println("sb.toString() = " + sb.toString());this.back();String s = sb.toString().trim();// System.out.println("s = " + s);if ("".equals(s)) {throw new JSONException("JSON语法错误");} else {// stringToValuereturn s;}// break;}return null;}/*** @param quote \'* @return key*/public String nextString(char quote) {StringBuilder sb = new StringBuilder();while (true) {// achar c = this.next();switch (c) {// 包含 空格、换行// Windows : \r\n// Linux: \r// Mac: \ncase '\u0000':case '\r':case '\n':throw new JSONException("json格式错误");// 匹配转义字符// \r// \t// \\case '\\':c = this.next();switch (c) {// 转义符case '\'':case '"':case '\\':case '/':sb.append(c);continue;// 匹配回车 换行 制表符....// \b \f \n \r \tcase 'b':sb.append('\b');continue;case 'f':sb.append('\f');continue;case 'n':sb.append('\n');continue;case 'r':sb.append('\r');continue;case 't':sb.append('\t');continue;default:throw new JSONException("非法转义字符 \\" + c);}default:if (c == quote) {return sb.toString();}sb.append(c);}}}}
注解
注释,解释是代码级别的说明,增强代码的作用性,对于反射,只能反射RUNNTIME注解。
原注解
作用在注解上的注解
@Target
指示注解类型适用的上下文。注解类型可能适用的声明上下文和类型上下文。
EelementType
这个枚举常量提供了Java程序中可能出现注解语法位置的简单分类,用于Target元注解,以指定写入给定类型注释的合法位置。
- ANNOTATION_TYPE:注解类型声明
- CONSTRUCTOR:构造函数声明
- FIELD:字段声明包括枚举常数
- METHOD:方法声明
- MODULE:模块声明
- PACKAGE:包装声明
- PARAMETER:参数声明
- TYPE:类、接口(包括注解类型)或枚举声明
- TYPE_PARAMETER:键入参数声明
- TYPE_USE:使用类型
@Retention
指示要注释具有注解类型的注解保留时间。如果注解类型声明中没有保留注解,则保留策略默认为RetentionPolicy.CLASS。保留原注注解仅在原注解类型直接用于注解时才起作用。如果原注解类型用作另一注解类型的成员类型,则它不起作用。
Retention Policy
- CLASS:注解将由编译器记录在类文件中,但VM不需要在运行时保留。
- SOURCE:注解将由编译器丢弃。
- RUNTIME:注解将被编译器记录在类文件中,并由VM在运行时保留,因此可以反射获取。
