反射
类加载器
类加载
当程序要使用某个类时,如果该类还没有加载到内存中,则系统会通过类的加载、类的连接、类的初始化这三个步骤来对类进行初始化。如果不出现意外情况,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. 普通对象 -> json
Student o = new Student(19, "zs");
System.out.println(JSON.toJSONString(o));
// 6. 数组对象 -> json
List<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. 普通对象 -> json
Student o = new Student(19, "zs");
System.out.println(gson.toJson(o));
// 6. 数组对象 -> json
List<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();
// 读取对象的key
String 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);
}
// 读取对象的value
this.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;
}
}
// 记录索引+1
this.index++;
// 换行符
/*
* ASCII:
* 0 空字符
* 1 标题开始
* 10 换行键
* */
if (c == '\r') {
// 记录行数+1
this.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 {
// stringToValue
return s;
}
// break;
}
return null;
}
/**
* @param quote \'
* @return key
*/
public String nextString(char quote) {
StringBuilder sb = new StringBuilder();
while (true) {
// a
char c = this.next();
switch (c) {
// 包含 空格、换行
// Windows : \r\n
// Linux: \r
// Mac: \n
case '\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 \t
case '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在运行时保留,因此可以反射获取。