1,反射获取类结构信息

在反射机制的处理过程之中不仅仅只是一个实例化对象的处理操作,更多的情况下还有类的组成结构操作,任何一个类的基本组成结构:父类(父接口)、包、属性、方法(构造方法与普通方法)。

获取类的基本信息

一个类的基本信息主要包括所在的包名称、父类的定义、父接口的定义。

·范例:定义一个程序类

1 packagecn.mufasa.vo;

2 public interfaceIMessageService {

3 public voidsend();

4 }

5 public interfaceIChannelService {

6 public booleanconnect();

7 }

8 importcn.mufasa.abs.AbstractBase;

9 public class Person extends AbstractBase implementsIMessageService,IChannelService {

10 @Override

11 public voidsend() {

12 if(this.connect()){

13 System.out.println("【消息发送】www.cnblogs.com");

14 }

15 }

16 @Override

17 public booleanconnect() {

18 return true;

19 }

20 }

1 packagecn.mufasa.abs;

2 public abstract classAbstractBase {

3 }

如果此时想要获取类的基础信息则可以通过Class类中如下方法:

①获取包名称:public Package getPackage();

1 packagecn.mufasa.demo;

2 importcn.mufasa.vo.Person;

3 public classJavaAPIDemo17 {

4 public static voidmain(String[] args) {

5 Class> cls=Person.class;//获取指定类的Class对象

6 Package pack=cls.getPackage();//获取指定类的包定义

7 System.out.println(pack.getName());

8 }

9 }

10 /*输出

11 cn.mufasa.vo

12 */

②获取继承父类:

1 packagecn.mufasa.demo;

2 importcn.mufasa.vo.Person;

3 public classJavaAPIDemo18 {

4 public static voidmain(String[] args) {

5 Class> cls=Person.class;

6 Class> parent=cls.getSuperclass();//获取继承父类的Class对象

7 System.out.println(parent.getName());

8 System.out.println(parent.getSuperclass().getName());

9 System.out.println(parent.getSuperclass().getSuperclass());

10 }

11 }

12 /*输出

13 cn.mufasa.abs.AbstractBase

14 java.lang.Object

15 null

16 */

③获取实现父接口:

1 packagecn.mufasa.demo;

2 importcn.mufasa.vo.Person;

3 public classJavaAPIDemo19 {

4 public static voidmain(String[] args) {

5 Class> cls=Person.class;

6 Class> [] classes=cls.getInterfaces();//获取继父接口

7 for(Class>temp : classes){

8 System.out.println(temp.getName());

9 }

10 }

11 }

12 /*输出

13 cn.mufasa.vo.IMessageService

14 cn.mufasa.vo.IChannelService

15 */

当获取了一个类的Class对象之后就意味着这个对象可以获取类之中的一切继承结构信息。

2,反射调用构造方法

在一个类之中除了有继承的关系之外最重要的操作就是类中的结构处理了,而类中的结构里面首先需要观察的就是构造方法的使用问题。实际上在之前通过反射实例化对象的时候就已经接触到了构造方法的问题了:

·实例化方法替代:clazz.getDeclaredConstructor().newInstance();

所有类的构造方法的获取都可以直接通过Class类来完成,该类中定义有如下几个方法:

·获取所有构造方法:public Constructor>[] getDeclaredConstructors() throws SecurityException

·获取指定构造方法:public Constructor getDeclaredConstructor(Class>... parameterTypes) throws NoSuchMethodException,SecurityException

·获取所有构造方法:public Constructor>[] getConstructors() throws SecurityException

·获取指定构造方法:public Constructor getConstructor(Class>... parameterTypes) throws NoSuchMethodException,SecurityException

·范例:修改Person类的定义

1 packagecn.mufasa.abs;

2 public abstract classAbstractBase1 {

3 public AbstractBase1(){}//无参

4 public AbstractBase1(String msg){}//有参

5 }

1 packagecn.mufasa.vo;

2 importcn.mufasa.abs.AbstractBase;

3 public class Person1 extends AbstractBase implementsIMessageService,IChannelService {

4 publicPerson1(){}

5 public Person1(String name,intage){

6 }

7 @Override

8 public voidsend() {

9 if(this.connect()){

10 System.out.println("【消息发送】www.cnblogs.com");

11 }

12 }

13 @Override

14 public booleanconnect() {

15 return true;

16 }

17 }

·范例:获取构造

1 packagecn.mufasa.demo;

2 importcn.mufasa.vo.Person1;

3 importjava.lang.reflect.Constructor;

4 public classJavaAPIDemo20 {

5 public static voidmain(String[] args) {

6 Class> cls=Person1.class;

7 // Constructor>[] constructors=cls.getDeclaredConstructors();

8 Constructor>[] constructors=cls.getConstructors();

9 for(Constructor>cons : constructors){

10 System.out.println(cons);

11 }

12 }

13 }

14 /*输出

15 public cn.mufasa.vo.Person1()

16 public cn.mufasa.vo.Person1(java.lang.String,int)

17 public cn.mufasa.vo.Person1()

18 public cn.mufasa.vo.Person1(java.lang.String,int)

19 */

此时获取的是类之中的全部构造方法,但是也可以获取一个指定参数的构造,例如:现在的Person1类之中提供有两个构造方法

1 packagecn.mufasa.vo;

2 importcn.mufasa.abs.AbstractBase;

3 public class Person1 extends AbstractBase implementsIMessageService,IChannelService {

4 privateString name;

5 private intage;

6 publicPerson1(){}

7 public Person1(String name,intage){

8 this.name=name;

9 this.age=age;

10 }

11 publicString toString(){

12 return "姓名:"+this.name+",年龄:"+this.age;

13 }

14 @Override

15 public voidsend() {

16 if(this.connect()){

17 System.out.println("【消息发送】www.cnblogs.com");

18 }

19 }

20 @Override

21 public booleanconnect() {

22 return true;

23 }

24 }

此时打算调用Person类之中的有参构造方法进行Person1类的实例化处理,这个时候就必须指明要调用的构造,而后通过Constractor类之中提供的实例化方法操作:

public T newInstance(Object... initargs) throws InstantiationException,IllegalAccessException,IllegalArgumentException,InvocationTargetException

·范例:调用指定构造实例化对象

1 packagecn.mufasa.demo;

2 importcn.mufasa.vo.Person1;

3 importjava.lang.reflect.Constructor;

4 importjava.lang.reflect.InvocationTargetException;

5 public classJavaAPIDemo21 {

6 public static void main(String[] args) throwsException {

7 Class> cls=Person1.class;

8 Constructor>constructor=cls.getConstructor(String.class,int.class);

9 Object obj=constructor.newInstance("万雨",25);

10 System.out.println(obj);

11 }

12 }

13 /*输出

14 姓名:万雨,年龄:25

15 */

虽然代码本身允许开发者调用有参构造处理,但是从实际的开发来讲,所有的使用反射的类中最好提供有无参构造,因为这样的实例化可以达到统一性。

3,反射调用普通方法

在进行反射处理的时候也可以获取类中的全部方法,但是需要提醒的是,如果想要通过反射调用这些方法必须有一个前提条件:类之中要提供实例化对象。

在Class类里面提供有如下的操作可以获取对象的方法:

①获取全部方法:public Method[] getMethods() throws SecurityException

②获取指定方法:public Method getMethod(String name,Class>... parameterTypes) throws NoSuchMethodException,SecurityException

③获取本类全部方法:public Method[] getDeclaredMethods() throws SecurityException

④获取本类指定方法:public Method getDeclaredMethod(String name,Class>... parameterTypes) throws NoSuchMethodException,SecurityException

·范例:获取全部方法

1 packagecn.demo8.demo;

2 importcn.mufasa.vo.Person1;

3 importjava.lang.reflect.Method;

4 public classJavaAPIDemo {

5 public static void main(String[] args) throwsException {

6 Class> cls=Person1.class;

7 {//获取全部方法【包括父类的方法】

8 Method[] methods=cls.getMethods();

9 for(Method met:methods){

10 System.out.println(met);

11 }

12 }

13 System.out.println("********分割线*********");

14 {//获取本类方法【包括父类的方法】

15 Method[] methods=cls.getDeclaredMethods();

16 for(Method met:methods){

17 System.out.println(met);

18 }

19 }

20 }

21 }

22 /*输出

23 public java.lang.String cn.mufasa.vo.Person1.toString()

24 public boolean cn.mufasa.vo.Person1.connect()

25 public void cn.mufasa.vo.Person1.send()

26 public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException

27 public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException

28 public final void java.lang.Object.wait() throws java.lang.InterruptedException

29 public boolean java.lang.Object.equals(java.lang.Object)

30 public native int java.lang.Object.hashCode()

31 public final native java.lang.Class java.lang.Object.getClass()

32 public final native void java.lang.Object.notify()

33 public final native void java.lang.Object.notifyAll()

34 ********分割线*********

35 public java.lang.String cn.mufasa.vo.Person1.toString()

36 public boolean cn.mufasa.vo.Person1.connect()

37 public void cn.mufasa.vo.Person1.send()

38 */

但是需要注意的是,这个时候方法信息的获取是根据Method类提供的toString()方法完成的,很多时候也可以由用户自己来拼凑方法信息的展示形式。

·范例:自定义方法信息显示

1 packagecn.demo8.demo;

2 importcn.mufasa.vo.Person1;

3 importjava.lang.reflect.Method;

4 importjava.lang.reflect.Modifier;

5 public classJavaAPIDemo1 {

6 public static void main(String[] args) throwsException {

7 Class> cls=Person1.class;

8 {

9 Method[] methods=cls.getMethods();//获取全部方法【包括父类的方法】

10 for(Method met:methods){

11 int mod=met.getModifiers();//修饰符【编码!!!】求和!

12 System.out.print(Modifier.toString(mod)+" ");//打印修饰符

13 System.out.print(met.getReturnType().getName()+" ");//打印返回值

14 System.out.print(met.getName()+"(");//打印方法名

15 Class>[] params=met.getParameterTypes();//获取参数类型

16 for(int x=0;x

17 System.out.print(params[x].getName()+" "+"arg-"+x);

18 if(x

19 System.out.print(",");

20 }

21 }

22 System.out.print(")");

23 Class>[] exp=met.getExceptionTypes();

24 if(exp.length>0){

25 System.out.print(" throws ");

26 }

27 for(int x=0;x

28 System.out.print(exp[x].getName());

29 if(x

30 System.out.print(",");

31 }

32 }

33 System.out.println();

34 }

35 }

36 }

37 }

38 /*输出

39 public java.lang.String toString()

40 public boolean connect()

41 public void send()

42 public final native void wait(long arg-0) throws java.lang.InterruptedException

43 public final void wait(long arg-0,int arg-1) throws java.lang.InterruptedException

44 public final void wait() throws java.lang.InterruptedException

45 public boolean equals(java.lang.Object arg-0)

46 public native int hashCode()

47 public final native java.lang.Class getClass()

48 public final native void notify()

49 public final native void notifyAll()

50 */

这种代码你只需要清楚可以根据反射获取方法的结构即可,不需要做过多的深入理解,但是在Method类里面有一个致命的重要方法:

public Object invoke(Object obj,Object... args)throws IllegalAccessException,IllegalArgumentException,InvocationTargetException

在Person类里面追加有setter和getter方法。

1 packagecn.demo8.demo;

2 importcn.mufasa.abs.AbstractBase;

3 public class Person2 extends AbstractBase implementsIMessageService, IChannelService {

4 privateString name;

5 private intage;

6 publicPerson2(){}

7 public Person2(String name, intage){

8 this.name=name;

9 this.age=age;

10 }

11 publicString getName() {

12 returnname;

13 }

14 public voidsetName(String name) {

15 this.name =name;

16 }

17 publicString toString(){

18 return "姓名:"+this.name+",年龄:"+this.age;

19 }

20 @Override

21 public voidsend() {

22 if(this.connect()){

23 System.out.println("【消息发送】www.cnblogs.com");

24 }

25 }

26 @Override

27 public booleanconnect() {

28 return true;

29 }

30 }

随后通过反射机制来实现Person类之中的setter与getter方法的调用处理。

·范例:在不导入指定类开发包的情况下实现属性的配置

1 packagecn.demo8.demo;

2 importjava.lang.reflect.Method;

3 public classJavaAPIDemo2 {

4 public static void main(String[] args) throwsException {

5 Class> cls=Class.forName("cn.demo8.demo.Person2");

6 // String attribute="name";//要操作的属性

7 String value="红红";//要设置的属性内容

8 //①任何情况下如果想要保存类中的属性或者调用类中的方法都必须保证存在有实例化对象,既然不允许导入包,那么就反射实例化

9 Object obj=cls.getDeclaredConstructor().newInstance();//调用无参构造

10 //②如果想要进行方法的调用,一定要获取方法的名称

11 String setMethodName="setName";//方法名称

12 Method setMethod=cls.getDeclaredMethod(setMethodName,String.class);//获取指定方法

13 setMethod.invoke(obj,value);//等价于:Person对象.setName(value);

14 String getMethodName="getName";

15 Method getMethod=cls.getDeclaredMethod(getMethodName);//getter方法没有传入参数

16 System.out.println(getMethod.invoke(obj));

17 }

18 }

19 /*输出

20 红红

21 */

利用此类操作整体的形式上不会有任何的明确类对象的产生,一切都是依靠反射机制处理的,这样的处理避免了与某一个类的耦合问题。

4,反射调用成员

类结构之中的最后一个核心的成员就是成员【Feild】,大部分情况下都会将其称为成员属性,对于成员信息的获取也是通过Class类完成的,在这个类中提供有如下两组操作方法:

①获取本类成员:public Field[] getDeclaredFields() throws SecurityException

②获取指定成员:public Field getDeclaredField(String name) throws NoSuchFieldException,SecurityException

③获取父类全部成员:public Field[] getFields() throws SecurityException

④获取父类指定成员:public Field getField(String name) throws NoSuchFieldException,SecurityException

·范例:修改要操作的父类结构

1 packagecn.demo9.demo;

2

3 public abstract classAbstractBase {

4 protected static final String NAME="www.cnblog.com";

5 private String info="Hello 万雨";

6 public AbstractBase(){}//无参

7 public AbstractBase(String msg){}//有参

8 }

1 packagecn.demo9.demo;

2

3 public interfaceIChannelService {

4 public static final String NAME="万雨";

5 public booleanconnect();

6 }

·范例:获取类中的成员

1 packagecn.demo9.demo;

2 importjava.lang.reflect.Field;

3

4 public classJavaAPIDemo {

5 public static void main(String[] args) throwsException {

6 Class> cls=Class.forName("cn.demo9.demo.Person");

7 {//获取父类中的公共信息

8 Field[] fields=cls.getFields();//获取父类成员

9 for(Field fie:fields){

10 System.out.println(fie);

11 }

12 }

13 System.out.println("*** 分割线 ***");

14 {//获取子类中的公共信息

15 Field[] fields=cls.getDeclaredFields();//获取成员

16 for(Field fie:fields){

17 System.out.println(fie);

18 }

19 }

20 }

21 }

22 /*输出

23 public static final java.lang.String cn.demo9.demo.IChannelService.NAME

24 *** 分割线 ***

25 private java.lang.String cn.demo9.demo.Person.name

26 private int cn.demo9.demo.Person.age

27 */

但是在Field类里面最为重要的操作形式并不是获取全部的成员,而是如下的三个方法:

①设置属性内容:public void set(Object obj,Object value)throws IllegalArgumentException,IllegalAccessException

②获取属性内容:public Object get(Object obj) throws IllegalArgumentException,IllegalAccessException

③解除封装:public void setAccessible(boolean flag) throws SecurityException,备注:构造可以解除封装、方法也可以解除封装

所有的成员是在对象实例化之后进行空间分配的,所以此时一定要先有实例化对象之后才可以进行成员的操作;

·范例:直接调用Person类中的name私有成员

1 packagecn.demo9.demo;

2 importjava.lang.reflect.Field;

3

4 public classJavaAPIDemo1 {

5 public static void main(String[] args) throwsException {

6 Class> cls=Class.forName("cn.demo9.demo.Person");

7 Object obj=cls.getConstructor().newInstance();//实例化对象【分配成员空间】

8 Field nameField=cls.getDeclaredField("name");//获取成员对象

9 nameField.setAccessible(true);//解除了封装

10 nameField.set(obj,"红红");//等价于:Person对象.name="红红";

11 System.out.println(nameField.get(obj));//等价于:Person对象.name;

12 }

13 }

14 /*输出

15 ①解除封装之前

16 Exception in thread "main" java.lang.IllegalAccessException: class cn.demo9.demo.JavaAPIDemo1 cannot access a member of class cn.demo9.demo.Person with modifiers "private"

17 ②解除封装之后

18 红红

19 */

通过一系列的分析可以发现,类之中的构造方法、成员属性都可以反射实现调用,但是对于成员的反射调用我们很少这样直接处理,大部分操作都应该通过setter或getter处理,所以说对于以上的代码只能够说是反射的一个特色,但是不具备有实际的使用能力,而对于Field类在实际开发之中只有一个方法最为常用:

获取成员类型:public Class> getType()

·范例:获取Person类中的name成员类型

1 packagecn.demo9.demo;

2 importjava.lang.reflect.Field;

3

4 public classJavaAPIDemo2 {

5 public static void main(String[] args) throwsException {

6 Class> cls = Class.forName("cn.demo9.demo.Person");

7 Field nameField = cls.getDeclaredField("name");//获取成员对象

8 System.out.println(nameField.getType().getName());//获取完整类名称【包.类】

9 System.out.println(nameField.getType().getSimpleName());//获取类名称

10 }

11 }

12 /*输出

13 java.lang.String

14 String

15 */

在以后的开发中进行反射处理的时候,往往会利用Field与Method类实现类中setter方法的调用。

5,Unsafe工具类

反射是Java的第一大特点,一旦打开了反射的大门就可以有了更加丰富的类设计形式。除了JVM本身支持的反射处理之外,子Java里面也提供有一个Unsafe类【不安全的操作】,这个类的主要特点是可以利用反射来获取对象,并且直接使用底层的C++来代替Java来执行,即:可以绕过JVM底层的相关的对象管理机制,如果你一旦使用了Unsafe类,那么你的项目之中将无法继续使用JVM的内存管理机制以及垃圾回收处理。

但是如果要想使用Unsafe类首先就需要确认一下这个类之中定义的构造方法与常量问题:

构造方法

private Unsafe() {}

私有常量

private static final Unsafe theUnsafe = new Unsafe();

但是需要注意的是,在这个Unsafe类里面并没有提供static方法,即:不能够通过类似于传统的单例设计模式之中提供的样式来进行操作,如果要想获得这个对象,就必须利用反射机制来完成。

1 Field field=Unsafe.class.getDeclaredField("theUnsafe");

2 field.setAccessible(true);//解除封装

3 Unsafe unsafeObject=(Unsafe) field.get(null);//static属性不需要传递实例化对象

在传统的开发之中,一个程序类必须要通过实例化对象后才可以调用类中个的普通方法,尤其是以单例设计模式为例

·范例:使用Unsafe类绕过实例化对象管理

1 packagecn.demo10.demo;

2

3 public classSingleton {

4 privateSingleton(){

5 System.out.print("【单例-私有构造】");

6 }

7 public voidprint(){

8 System.out.print("www.mldn.cn");

9 }

10 }

1 packagecn.demo10.demo;

2

3 importsun.misc.Unsafe;

4

5 importjava.lang.reflect.Field;

6

7 public classJavaAPIDemo2 {

8 public static void main(String[] args) throwsException {

9 Field field=Unsafe.class.getDeclaredField("theUnsafe");

10 field.setAccessible(true);//解除封装

11 Unsafe unsafeObject=(Unsafe) field.get(null);//static属性不需要传递实例化对象

12 //利用Unsafe类绕过了JVM的管理机制,可以在没有实例化对象的情况下获取一个Singleton类对象

13 Singleton singleton=(Singleton) unsafeObject.allocateInstance(Singleton.class);

14 singleton.print();

15

16 }

17 }

18 /*输出

19 www.mldn.cn

20 */

Unsafe只能够说为我们的开发提供了一些更加方便的处理机制,但是这种操作由于不受JVM的管理所以如果不是必须的情况下不建议使用,而讲解这个类主要的目的是帮助大家巩固对于反射的理解,同时也帮助大家在笔试的时候如果有人问到单例模式的情况下,也可以追加一个Unsafe以加深你对这一概念的理解。

java编程进阶类_进阶Java编程(9)反射与类操作相关推荐

  1. java项目----教务管理系统_基于Java的教务管理系统

    java项目----教务管理系统_基于Java的教务管理系统 2022-04-22 18:18·java基础 最近为客户开发了一套学校用教务管理系统,主要实现学生.课程.老师.选课等相关的信息化管理功 ...

  2. java编程定义狗_用Java创建一条自己diy的狗狗类(6)

    21.这是用Java创建一条自己diy的狗狗类的源代码可以直接进行编译运行,希望大家能够从中获益良多. //gougou类文件 package test; public class gougou { ...

  3. java编程思想怎么样_读完java编程思想后的思考?

    谢邀,这本书真的给我带来很多思考. 我的java入门不是java编程思想,学校的教材是一本紫色的书,已经忘了叫什么名字了,里面内容倒挺新还讲了些javafx.但那本书实在是太浅并且结构混乱,以至于我和 ...

  4. 黑马ee在职进阶视频_进阶– Java EE 7前端5强

    黑马ee在职进阶视频 系列继续. 在初步概述和Arjan关于最重要的后端功能的文章之后 ,我现在非常高兴让Ed Burns( @edburns )使用他最喜欢的Java EE 7前端功能完成本系列. ...

  5. java 是否含有日文_《JAVA编程思想》5分钟速成:第9章(接口)

    第9章 接口 前言: 1.抽象类(abstract class)和接口(interface)有什么异同? 2.抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(n ...

  6. java编程思想 初始化_《java编程思想》_第五章_初始化与清理

    初始化和清理是涉及安全的两个问题,java中采用了构造器,并额外提供了"垃圾回收器",对于不再使用的内存资源,垃圾回收器能自动将其释放. 一.用构造器确保初始化 java中,通过提 ...

  7. java枚举对象作用_浅析Java编程中枚举类型的定义与使用

    定义枚举类型时本质上就是在定义一个类,只不过很多细节由编译器帮您补齐了,所以某些程度上,enum关键字的 作用就像是class或interface. 当您使用"enum"定义枚举类 ...

  8. java中随机数怎么定义类_浅析Java中的随机数类

    Java中的随机数是否可以重复?Java中产生的随机数能否可以用来产生数据库主键?带着这个问题,我们做了一系列测试. 1.测试一: 使用不带参数的Random()构造函数 * @author Carl ...

  9. JAVA设计一个电视机类_漫谈Java程序设计中的接口应用

    Java语言提供了一种接口(interface)机制.这种接口机制使Java的面向对象编程变得更加灵活.我们可以用接口来定义一个类的表现形式,但接口不能包含任何实现.在<Thinking in ...

  10. java简单通讯录的实现02person类_用java实现简单的小游戏(你一定玩过)

    用java实现简单的小游戏(你一定玩过) 对于java初学者来说,通过一些学习小游戏来对swing学习以及对java基础的学习是一个好的方法,同时也给学习带来了很多的乐趣,接下来就给大家分享一个jav ...

最新文章

  1. context linux,使用selinux contexts
  2. [个人博客作业Week7]软件工程团队项目感想与反思
  3. 递归查询mysql数据库设计
  4. yii2 mysql查询_Yii2 数据库查询汇总
  5. ASP.NET Aries 4.0 开源发布:已完成基础功能优化重写
  6. 数据工作本质:从业务中来,到业务中去
  7. 撸一款Flutter版『微信』
  8. 软件开发有哪些规范和标准_车辆,机械专业如何从事汽车电子软件开发
  9. 记一次 Win 10 下的用户文件夹迁移
  10. 小布什逗留香港6小时 赴知名裁缝店做18套西装——中新网
  11. 【知识必备】RxJava+Retrofit二次封装最佳结合体验,打造懒人封装框架~
  12. mui用ajax上拉加载更多,mui 中的一个上拉加载及下拉刷新的方法 ,但是我使用ajax拿不到url中的数据,是为什么?...
  13. Oracle Golden Gate 系列二 -- GG 的系统需求
  14. 海洋cms播放器html,海洋cms升级新播放器后播放不了如何解决?
  15. python正则表达式例题_python—正则表达式实例
  16. java工具类 - word内容文本替换
  17. win10在此计算机上找不到系统映像,图文教你win10系统使用DISM修复找不到源的问题....
  18. 播放视频无声音,视频编码来解决
  19. 使用docker快速安装Oracle11gR2
  20. 尝试 对网游私人服务器架设的一些接触

热门文章

  1. flutter ListView.separated使用
  2. TypeScript瞎看看
  3. php echo字符串连接符逗号,和句号.的区别,使用实例
  4. 算法——霍夫曼编码压缩算法
  5. SGX Enable
  6. MacBook 如何使用两个微信(微信双开)
  7. 三层交换机也不贵:自己动手做三层交换机
  8. 愚人节整蛊,网页倾斜代码
  9. 辞旧迎新又一年(18年年终总结)
  10. 左斜杠和右斜杠的区别