Java-day17(反射)

Reflection(反射)

动态语言的关键

  • 允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法
  • 提供的功能:
    在运行时判断任意一个对象所属类
    在运行时构造任意一个类的对象
    在运行时判断任意一个类所具有的成员变量和方法
    在运行时调用任意一个对象的成员变量和方法
    生成动态代理
    在这里插入图片描述


Person类

@MyAnnotation(value = "atguigu")
public class Person extends Creature<String> implements Comparable,MyInsterface{   public String name;private int age;//创建类时,尽量保留一个空参的构造器public Person() {super();System.out.print("空参");}public Person(String name) {super();this.name = name;}public Person(String name, int age) {super();this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@MyAnnotation(value = "boos")public void show() {System.out.println("I am Person");}public void display(String nation)throws Exception {System.out.println("我的国籍是= " + nation);}private Integer displays(String nation,Integer i)throws Exception {System.out.println("我的国籍是= " + nation);return i;}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}@Overridepublic int compareTo(Object arg0) {// TODO Auto-generated method stubreturn 0;}public static void info() {System.out.println("Chianese");}class A {}
}

在这里插入图片描述

  • 没有反射之前,创建对象,调用方法,属性
@Test
public void test1() throws Exception {Person p = new Person();p.setName("HaoJie");p.setAge(22);System.out.println(p);                             p.show();p.display("中国");
}
  • 有反射之后,创建对象,调用方法,属性
@Test
public void test2() throws Exception{Class c = Person.class;//c直接指向Person实体(反射的源头java.lang.Class类)//1.创建c对应的运行时类Person类的对象Person p = (Person)c.newInstance();//2-1.通过反射获取实体的公有属性Field f1 = c.getField("name");f1.set(p,"LiYunHai");System.out.println(p);       //2-2.通过反射获取实体的私有属性Field f2 = c.getDeclaredField("age");f2.setAccessible(true);f2.set(p,26);System.out.println(p);  //通过反射调用运行时实体(类)的指定的方法Method m1 = c.getMethod("show");m1.invoke(p);Method m2 = c.getMethod("display",String.class);m2.invoke(p,"China");		
}

1.理解Class类并实例化Class类对象

在这里插入图片描述

  • 类的具体实现:
    在这里插入图片描述

    创建类,通过编译(javac.exe),生产字节码文件,之后通过java.exe加载(JVM的类加载器完成的)字节码文件,字节码文件加载到内存中,就是一个运行时类,存在缓冲区中。这个运行时类本身就是一个Class的实例
    在这里插入图片描述

  • 每一个运行时类只加载一次

  • 有Class的实例,就可以进行如下操作:

     //*创建对应的运行时类的对象//获取对应的运行时类的完整结构(属性,方法,构造器,内部类。。。)//*调用对应运行时类的指定的结构(属性,方法,构造器)//反射的应用:动态代理
    

获取Class的实例(掌握3种)

@Test
public void test4() throws ClassNotFoundException {//1.调用运行时类本身的.class属性Class clazz = Person.class;System.out.println(clazz.getName());                Class clazz1 = String.class;System.out.println(clazz1.getName());System.out.println();//2.通过运行时类的对象获取Person p = new Person();Class clazz2  = p.getClass();System.out.println(clazz2.getName());//3.通过Class的静态方法获取String classname = "java.lang.String";Class clazz3 = Class.forName(classname);System.out.println(clazz3.getName());//4.(了解)通过类的加载器ClassLoader classLoader = this.getClass().getClassLoader();Class clazz4 = classLoader.loadClass(classname);System.out.println(clazz4.getName());System.out.println(clazz1 == clazz3);//trueSystem.out.println(clazz1 == clazz2);//falseSystem.out.println(clazz1 == clazz4);//true
}

在这里插入图片描述
例:

@Test	public void test5() throws IOException {ClassLoader loader1 = ClassLoader.getSystemClassLoader();          System.out.println(loader1);//获取ClassLoader类的加载类AppClassLoaderClassLoader loader2 = loader1.getParent();System.out.println(loader2);//ExtClassLoaderClassLoader loader3 = loader2.getParent();System.out.println(loader3);//null(核心类库及引导类无法获取)Class clazz1 = Person.class;ClassLoader loader4 = clazz1.getClassLoader();System.out.println(loader4);//AppClassLoader}
	//掌握如下:查找包下的文件中的部分内容ClassLoader loader5 = this.getClass().getClassLoader();                  InputStream is = loader5.getResourceAsStream("hello.txt");//查找工程下的文件中的部分内容//FileInputStream is = new FileInputStream(new File("hello.txt"));Properties txt = new Properties();txt.load(is);String name = txt.getProperty("user");System.out.println(name);String password = txt.getProperty("password");System.out.println(password);

2.在运行时创建类对象并获取类的完整结构

在这里插入图片描述
例:

@Testpublic void test1() throws Exception {String className = "Person";                       Class clazz = Class.forName(className);  //创建对应的运行类的对象//要求:1.对应的运行时类要有空参的构造器;2.构造器的权限应在缺省(及以上)Object obj = clazz.newInstance();Person p = (Person)obj;System.out.print(p);  }@Test//构造器public void test2() throws ClassNotFoundException {String className = "Person";  Class clazz = Class.forName(className);  //getDeclaredConstructors():获取本身类所有的构造器Constructor[] cons = clazz.getDeclaredConstructors();for(Constructor c : cons) {  System.out.println(c);  }}
获取运行时类的方法
@Testpublic void test1() {Class clazz = Person.class;//1.getMethods():获取运行时类及其父类中所有声明为public的方法Method[] m1 = clazz.getMethods();for(Method m : m1) {       System.out.println(m);}System.out.println();//2.获取运行时类本身声明的所有方法Method[] m2 = clazz.getDeclaredMethods();for(Method m : m2) {System.out.println(m);}System.out.println();System.out.println();}
获取对应的运行时类的属性
@Testpublic void test1() {Class clazz = Person.class;//getFields():只能获取运行时类及其父类中声明为public的属性Field[] fields = clazz.getFields();for(int i = 0;i < fields.length;i++) {System.out.println(fields[i]);        }System.out.println();//2.getDeclaredFields():获取运行时类本身声明的所有属性Field[] fields1 = clazz.getDeclaredFields();for(Field f : fields1) {System.out.println(f.getName());}}
获取属性各个部分的内容(权限修饰符 变量类型 变量名)
@Testpublic void test2() {Class clazz = Person.class;Field[] fields = clazz.getDeclaredFields();for(Field f : fields) {//1.获取属性的权限修饰符int i = f.getModifiers();String str = Modifier.toString(i);System.out.print(str + " ");      //2.获取属性的类型Class type = f.getType();System.out.print(type.getName() + " ");//3.获取属性名System.out.print(f.getName());System.out.println();}}
注解 权限修饰符 返回值类型 方法名 形参列表 异常
@Testpublic void test2() {Class clazz = Person.class;Method[] m1 = clazz.getDeclaredMethods();for(Method m : m1) {   //1.注解Annotation[] ann = m.getAnnotations();for(Annotation an : ann) {System.out.println(an);}//2.权限修饰符String str = Modifier.toString(m.getModifiers());System.out.print(str + " ");//3.返回值类型Class returnType = m.getReturnType();System.out.print(returnType.getName() + " ");//4.方法名System.out.print(m.getName());//5.形参列表System.out.print("(");Class[] params = m.getParameterTypes();for(int i = 0;i < params.length;i++) {System.out.print(params[i].getName() + " args-" + i + " ");}System.out.print(")");//6.异常类型Class[] exps = m.getExceptionTypes();if(exps.length != 0) {System.out.print("throws ");}for(int i = 0;i < exps.length;i++) {System.out.print(exps[i].getName());}			System.out.println();}}

在这里插入图片描述

import java.lang.annotation.Retention;         
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
@Target({TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {String value();
}

带泛型的类

public class Creature<T> {public double weight; public void breath() {System.out.println("呼吸");}
}

接口

import java.io.Serializable;public interface MyInsterface extends Serializable{}

继承,实现接口等

@MyAnnotation(value = "atguigu")
public class Person extends Creature<String> implements Comparable,MyInsterface{  public String name;private int age;//创建类时,尽量保留一个空参的构造器public Person() {super();System.out.print("空参");}public Person(String name) {super();this.name = name;}public Person(String name, int age) {super();this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@MyAnnotation(value = "boos")public void show() {System.out.println("I am Person");}public void display(String nation)throws Exception {System.out.println("我的国籍是= " + nation);}private Integer displays(String nation,Integer i)throws Exception {System.out.println("我的国籍是= " + nation);return i;}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}@Overridepublic int compareTo(Object arg0) {// TODO Auto-generated method stubreturn 0;}public static void info() {System.out.println("Chianese");}class A {}
}

测试

import java.lang.annotation.Annotation;             
import java.lang.reflect.ParameterizedType; 
import java.lang.reflect.Type; import org.junit.Test;public class TestOther {@Test//1.获取运行时类的父类public void test1() {Class clazz = Person.class;Class superClass = clazz.getSuperclass();System.out.println(superClass);//class Creature }@Test//2.获取带泛型的父类public void test2() {Class clazz = Person.class;Type type = clazz.getGenericSuperclass();System.out.println(type);//Creature<java.lang.String> }@Test//3.获取父类的泛型public void test3() {Class clazz = Person.class;Type type = clazz.getGenericSuperclass();ParameterizedType param = (ParameterizedType)type; Type[] ars = param.getActualTypeArguments(); System.out.println(((Class)ars[0]).getName()); }@Test//获取实现的接口public void test4() {Class clazz = Person.class;Class[] interfaces = clazz.getInterfaces(); for(Class i : interfaces) { System.out.println(i); }}@Test//获取所在的包public void test5() {Class clazz = Person.class;Package pack = clazz.getPackage();System.out.println(pack); }@Test//获取注解public void test6() {Class clazz = Person.class;Annotation[] anns = clazz.getAnnotations();for(Annotation a : anns) {System.out.println(a); }}
}

3.通过反射调用类的指定方法,指定属性

调用指定构造器,创建对象
@Test//public void test3() throws Exception {String className = "Person";    Class clazz = Class.forName(className);Constructor cons = clazz.getDeclaredConstructor(String.class,int.class);cons.setAccessible(true);Person p = (Person)cons.newInstance("李福根",56);System.out.println(p);}
调用运行时类中指定的属性
@Testpublic void test3() throws Exception {Class clazz = Person.class;//1.获取指定的属性//getField(String fielName):获取运行时类中声明为public类型的指定属性名为fielName的属性Field name = clazz.getField("name");//2.创建运行时类的对象Person p = (Person)clazz.newInstance();System.out.println(p);        //3.将运行时指定的属性赋值name.set(p, "Jame");System.out.println(p);System.out.println();//getDeclaredField(String fielName):获取运行时类中指定属性名为fielName的属性Field age = clazz.getDeclaredField("age");//私有属性不能直接用getField来调//由于权限修饰符的限制,为保证可以给属性赋值,需要在操作前使此属性可被操作(缺省状态下,可不用)age.setAccessible(true);age.set(p, 25);System.out.println(p);}
调用运行时类的指定方法
@Testpublic void test3() throws Exception {Class clazz = Person.class;//getMethod(String methodName,Class .. params):获取运行时类中声明为public的指定方法Method m1 = clazz.getMethod("show");Person p = (Person)clazz.newInstance();//调用指定的方法:Object invoke(Object obj,Object ... obj)            Object returnVal = m1.invoke(p);//方法本身无返回值,就显示为nullSystem.out.println(returnVal);Method m2 = clazz.getMethod("toString");Object returnVal1 = m2.invoke(p);System.out.println(returnVal1);//方法本身有返回值,就显示为方法的返回值//调用静态的方法Method m3 = clazz.getMethod("info");m3.invoke(Person.class);//不需要对象//getDeclaredMethod(String methodName,Class .. params):获取运行时类中声明的指定方法Method m4 = clazz.getDeclaredMethod("displays",String.class,Integer.class);m4.setAccessible(true);Object returnVal2 = m4.invoke(p,"CNN",10);//调用方法System.out.println(returnVal2);//返回值}

4.动态代理与AOP

静态代理

package Proxy;     
//接口
interface ClothFactory{void productCloth();
}
//被代理类
class NikeClothFactory implements ClothFactory{@Overridepublic void productCloth() {System.out.println("Nike工厂开工了!");	}
}//代理类
class ProxyFactory implements ClothFactory{ClothFactory cf;//创建代理类的对象时,实际传入一个被代理类的对象public ProxyFactory(ClothFactory cf) {this.cf = cf;}@Overridepublic void productCloth() {System.out.println("代理开始,收专利费了!");cf.productCloth();}}
public class TestCiothProduct {public static void main(String[] args) {	NikeClothFactory nike = new NikeClothFactory();//被代理类ProxyFactory proxy = new ProxyFactory(nike);//代理类proxy.productCloth();
}
}
动态代理

在这里插入图片描述
在这里插入图片描述

package Proxy;  import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;//动态代理
interface Subject{void action();
}
//被代理类
class ReaSubject implements Subject{public void action() {System.out.println("我是被代理类,好囧ing");}
}class MyInvocationHandler implements InvocationHandler{Object obj;//实现接口的被代理类对象的声明//给被代理的对象实例化;返回一个代理类的对象声明public Object blind(Object obj) {this.obj = obj;return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);}@Override//当通过代理类的对象发起被重写的方法的调用时,都会转换为对如下invoke方法的调用public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//method方法的返回值是returnValSystem.out.println("代理------");Object returnVal = method.invoke(obj, args);return returnVal;}
}
public class dongProxy {public static void main(String[] args) {//1.被代理类的对象ReaSubject real = new ReaSubject();//2.创建实现InvocationHandler接口的类对象MyInvocationHandler handler = new MyInvocationHandler();//3.调用blind()方法,动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象Object obj = handler.blind(real);Subject sub = (Subject)obj;//此时的sub就是代理类的对象sub.action();//跳转到InvocationHandler接口的实现类的invoke()方法的调用//例NikeClothFactory nike = new NikeClothFactory();//被代理类ClothFactory proxyCloth = (ClothFactory)handler.blind(nike);//proxyCloth即为代理类的对象proxyCloth.productCloth();}
}
动态代理与AOP

在这里插入图片描述
在这里插入图片描述
例:

package com.al.java;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;interface Human{void info();void fly();   
}
//被代理类
class SuperMan implements Human{public void info() {System.out.println("我是超人");}public void fly() {System.out.println("I believe I can fly!");}
}
class HumanUtil{public void method1() {System.out.println("========方法一======");}public void method2() {System.out.println("========方法二======");}
}class MyInvocationHandler implements InvocationHandler{Object obj;public void setObject(Object obj) {this.obj = obj;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {HumanUtil h = new HumanUtil();h.method1();Object returnval = method.invoke(obj, args);h.method2();return returnval;}}class MyProxy{//动态的创建一个代理类对象public static Object getProxyInstance(Object obj) {MyInvocationHandler handler = new MyInvocationHandler();handler.setObject(obj);return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);}
}public class TestAOP {public static void main(String[] args) {	SuperMan man = new SuperMan();//创建被代理类对象Object obj = MyProxy.getProxyInstance(man);//返回代理类对象Human hu = (Human)obj;hu.info();//通过代理类的对象调用重写的抽象方法System.out.println();hu.fly();}
}

运行示例
请添加图片描述
感谢大家的支持,关注,评论,点赞!
参考资料:
尚硅谷宋红康20天搞定Java基础下部

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/87631.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怒刷LeetCode的第15天(Java版)

目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;哈希表双向链表 方法二&#xff1a;TreeMap 方法三&#xff1a;双哈希表 第二题 题目来源 题目内容 解决方法 方法一&#xff1a;二分查找 方法二&#xff1a;线性搜索 方法三&#xff1a;Arrays类的b…

基于SpringBoot的在线文档管理系统

目录 前言 一、技术栈 二、系统功能介绍 管理员功能模块 员工功能模块 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势…

ArcGIS 10.3软件安装包下载及安装教程!

【软件名称】&#xff1a;ArcGIS 10.3 【安装环境】&#xff1a;Windows 【下载链接 】&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1K5ab7IHMYa23HpmuPkFa1A 提取码&#xff1a;oxbb 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 软件解压码点击原文…

java面试题-jvm基础知识

1 JVM组成 1.1 JVM由那些部分组成&#xff0c;运行流程是什么&#xff1f; 难易程度&#xff1a;☆☆☆ 出现频率&#xff1a;☆☆☆☆ JVM是什么 Java Virtual Machine Java程序的运行环境&#xff08;java二进制字节码的运行环境&#xff09; 好处&#xff1a; 一次编写&a…

代码随想录算法训练营day6| 哈希表理论基础、242.有效的字母异位词、349. 两个数组的交集、202. 快乐数、1. 两数之和

目录 一、哈希表理论 hash function ​编辑hash collision 常见哈希结构 1&#xff09;set 2&#xff09;map 二、&#xff08;leetcode 242&#xff09;有效的字母异位词 三、&#xff08;leetcode 349&#xff09;两个数组的交集 四、&#xff08;leetcode 202&…

JAVA学习-全网最详细

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

Linux学习第19天:Linux并发与竞争实例: 没有规矩不成方圆

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 先说点题外话&#xff0c;上周参加行业年会&#xff0c;停更了一周。接下来的周五就要开启国庆中秋双节模式&#xff0c;所以有的时候&#xff0c;尤其是工作以后…

java面试题-设计模式基础

面试专题-设计模式 前言 在平时的开发中&#xff0c;涉及到设计模式的有两块内容&#xff0c;第一个是我们平时使用的框架&#xff08;比如spring、mybatis等&#xff09;&#xff0c;第二个是我们自己开发业务使用的设计模式。 面试官一般比较关心的是你在开发过程中&#…

游戏录屏软件推荐,教你录制高清游戏视频

“有没有好用的游戏录屏软件推荐呀&#xff0c;最近当上了游戏主播&#xff0c;平台要求每天都要发一个游戏视频&#xff0c;可是我的游戏录屏软件太拉胯了&#xff0c;录制出来的视频非常糊&#xff0c;导致平台审核不通过&#xff0c;所以想问问大家有没有游戏录屏软件推荐一…

SQL server 创建存储过程

SQL Server如何创建存储过程 存储过程&#xff1a; 可以理解为完成特定功能的一组 SQL 语句集&#xff0c;存储在数据库中&#xff0c;经过第一次编译&#xff0c;之后的运行不需要再次编译&#xff0c;用户通过指定存储过程的名字并给出参数&#xff08;如果该存储过程带有参数…

时序分解 | Matlab实现CEEMD互补集合经验模态分解时间序列信号分解

时序分解 | Matlab实现CEEMD互补集合经验模态分解时间序列信号分解 目录 时序分解 | Matlab实现CEEMD互补集合经验模态分解时间序列信号分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab实现CEEMD互补集合经验模态分解时间序列信号分解 1.分解效果图 &#xff0…

opencv dnn模块 示例(17) 目标检测 object_detection 之 yolo v5

在前文【opencv dnn模块 示例(16) 目标检测 object_detection 之 yolov4】介绍的yolo v4后的2个月&#xff0c;Ultralytics发布了YOLOV5 的第一个正式版本&#xff0c;其性能与YOLO V4不相伯仲。 文章目录 1、Yolo v5 和 Yolo v4 的区别说明1.1、Data Augmentation - 数据增强1…

vue3【echarts 做的词云图】

效果图 安装 安装echarts npm install echarts安装词云图 npm install echarts-wordcloudecharts-wordcloud的git仓库地址 echarts官网地址 引用 import * as ECharts from "echarts"; //引用eacharts import echarts-wordcloud;//引用云词这里的echarts 是自己简…

PHP8的类与对象的基本操作之类的实例化-PHP8知识详解

定义完类和方法后&#xff0c;并不是真正创建一个对象。类和对象可以描述为如下关系。类用来描述具有相同数据结构和特征的“一组对象”&#xff0c;“类”是“对象”的抽象&#xff0c;而“对象”是“类”的具体实例&#xff0c;即一个类中的对象具有相同的“型”&#xff0c;…

【Solidity】Solidity Keccak256 与 SHA3-256

Solidity Keccak256 与 SHA3-256 文章目录 前言什么是 SHA3Keccak256 和 SHA3-256 有什么区别?为何推出sha3参考区块链的造富神话大家一定都有所耳闻,今天我们讨论以太坊中一项基础技术,主打一个一学就会。 前言 看过以太坊源码或者对区块链有了解的的同学,一定都见过一个…

华为 Mate60 系列全球发布:地表最强黑科技旗舰,打破传统,引领未来!

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

Amazon Lightsail——兼具亚马逊云科技的强大功能与 VPS 的简易性

对于开发者而言&#xff0c;当你想构建系统架构时&#xff0c;你的面前就出现了两种选择&#xff0c;选择一&#xff1a;花时间去亲手挑选每个亚马逊云科技组件&#xff08;云服务器、存储、IP 地址等&#xff09;&#xff0c;然后自己组装起来&#xff1b;选择二是只需要一个预…

WebGL HUD(平视显示器)

目录 HUD&#xff08;平视显示器&#xff09; 如何实现HUD 示例程序&#xff08;HUD.html&#xff09; 示例程序&#xff08;HUD.js&#xff09; 代码详解 在网页文字上方显示三维物体 代码详解 HUD&#xff08;平视显示器&#xff09; 平视显示器&#xff08;head…

展示日志log4.properties

log4.properties 1.log4.properties 此时文件主要用于展示日志的输出的级别的信息。 # Set root category priority to INFO and its only appender to CONSOLE. #log4j.rootCategoryINFO, CONSOLE debug info warn error fatal log4j.rootCategoryinfo, CONSO…

算法通过村第九关-二分(中序遍历)黄金笔记|二叉搜索树

文章目录 前言1. 有序数组转二叉搜索树2. 寻找连个正序数组的中位数总结 前言 提示&#xff1a;有时候&#xff0c;我感觉自己一辈子活在两个闹钟之间&#xff0c;早上的第一次闹钟&#xff0c;以及5分钟之后的第二次闹钟。 --奥利弗萨克斯《意识的河流》 每个专题都有简单题&a…