1.集合类

主要掌握如何实现.

ArrayList实现原理要点概括

ArrayList是List接口的可变数组非同步实现,并允许包括null在内的所有元素。
底层使用数组实现
该集合是可变长度数组,数组扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量增长大约是其容量的1.5倍,这种操作的代价很高。
采用了Fail-Fast机制,面对并发的修改时,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险
remove方法会让下标到数组末尾的元素向前移动一个单位,并把最后一位的值置空,方便GC

LinkedList实现原理要点概括
LinkedList是List接口的双向链表非同步实现,并允许包括null在内的所有元素。
底层的数据结构是基于双向链表的,该数据结构我们称为节点
双向链表节点对应的类Node的实例,Node中包含成员变量:prev,next,item。其中,prev是该节点的上一个节点,next是该节点的下一个节点,item是该节点所包含的值。
它的查找是分两半查找,先判断index是在链表的哪一半,然后再去对应区域查找,这样最多只要遍历链表的一半节点即可找到

HashMap实现原理要点概括
HashMap是基于哈希表的Map接口的非同步实现,允许使用null值和null键,但不保证映射的顺序。
底层使用数组实现,数组中每一项是个单向链表,即数组和链表的结合体;当链表长度大于一定阈值时,链表转换为红黑树,这样减少链表查询时间。
HashMap在底层将key-value当成一个整体进行处理,这个整体就是一个Node对象。HashMap底层采用一个Node[]数组来保存所有的key-value对,当需要存储一个Node对象时,会根据key的hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Node时,也会根据key的hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Node。
HashMap进行数组扩容需要重新计算扩容后每个元素在数组中的位置,很耗性能
采用了Fail-Fast机制,通过一个modCount值记录修改次数,对HashMap内容的修改都将增加这个值。迭代器初始化过程中会将这个值赋给迭代器的expectedModCount,在迭代过程中,判断modCount跟expectedModCount是否相等,如果不相等就表示已经有其他线程修改了Map,马上抛出异常

Hashtable实现原理要点概括
Hashtable是基于哈希表的Map接口的同步实现,不允许使用null值和null键
底层使用数组实现,数组中每一项是个单链表,即数组和链表的结合体
Hashtable在底层将key-value当成一个整体进行处理,这个整体就是一个Entry对象。Hashtable底层采用一个Entry[]数组来保存所有的key-value对,当需要存储一个Entry对象时,会根据key的hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,也会根据key的hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Entry。
synchronized是针对整张Hash表的,即每次锁住整张表让线程独占

ConcurrentHashMap实现原理要点概括
ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术。
它使用了多个锁来控制对hash表的不同段进行的修改,每个段其实就是一个小的hashtable,它们有自己的锁。只要多个并发发生在不同的段上,它们就可以并发进行。
ConcurrentHashMap在底层将key-value当成一个整体进行处理,这个整体就是一个Entry对象。Hashtable底层采用一个Entry[]数组来保存所有的key-value对,当需要存储一个Entry对象时,会根据key的hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,也会根据key的hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Entry。
与HashMap不同的是,ConcurrentHashMap使用多个子Hash表,也就是段(Segment)
ConcurrentHashMap完全允许多个读操作并发进行,读操作并不需要加锁。如果使用传统的技术,如HashMap中的实现,如果允许可以在hash链的中间添加或删除元素,读操作不加锁将得到不一致的数据。ConcurrentHashMap实现技术是保证HashEntry几乎是不可变的。

HashSet实现原理要点概括
HashSet由哈希表(实际上是一个HashMap实例)支持,不保证set的迭代顺序,并允许使用null元素。
基于HashMap实现,API也是对HashMap的行为进行了封装,可参考HashMap

LinkedHashMap实现原理要点概括
LinkedHashMap继承于HashMap,底层使用哈希表和双向链表来保存所有元素,并且它是非同步,允许使用null值和null键。
基本操作与父类HashMap相似,通过重写HashMap相关方法,重新定义了数组中保存的元素Entry,来实现自己的链接列表特性。该Entry除了保存当前对象的引用外,还保存了其上一个元素before和下一个元素after的引用,从而构成了双向链接列表。

LinkedHashSet实现原理要点概括
对于LinkedHashSet而言,它继承与HashSet、又基于LinkedHashMap来实现的。LinkedHashSet底层使用LinkedHashMap来保存所有元素,它继承与HashSet,其所有的方法操作上又与HashSet相同。

2.动态代理与反射
是java语言的特色,需要掌握动态代理与反射的使用场景.
ORM框架中会大量使用代理类,PRC调用时使用反射机制调用实现类的方法.

java的动态代理是用反射实现的。

什么是反射?
java的反射机制,是说在运行时刻,对于任何一个类,都能够知道它的所有属性和方法;对任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用方法的功能称为java的反射机制。

java通过java.lang.Class类实现反射机制。

Class类的getDeclaredMethod可以根据方法名字返回一个方法:

// 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
Method getDeclaredMethod(String name, Class<?>... parameterTypes)
1
2
Method的invoke方法可以执行这个方法:

// 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
Object invoke(Object obj, Object... args)

3.数据类型
也是面试的常见问题.如每种数据类型占用多大空间,数据类型的自动转换与强制转换,基础数据类型与Wrapper数据类型的自动装箱与拆箱等.

一、基本数据类型:

byte:Java中最小的数据类型,在内存中占8位(bit),即1个字节,取值范围-128~127,默认值0
short:短整型,在内存中占16位,即2个字节,取值范围-32768~32717,默认值0
int:整型,用于存储整数,在内在中占32位,即4个字节,取值范围-2147483648~2147483647,默认值0
long:长整型,在内存中占64位,即8个字节-2^63~2^63-1,默认值0L
float:浮点型,在内存中占32位,即4个字节,用于存储带小数点的数字(与double的区别在于float类型有效小数点只有6~7位),默认值0
double:双精度浮点型,用于存储带有小数点的数字,在内存中占64位,即8个字节,默认值
char:字符型,用于存储单个字符,占16位,即2个字节,取值范围0~65535,默认值为空
boolean:布尔类型,占1个字节,用于判断真或假(仅有两个值,即true、false),默认值false

Java数据类型在内存中的存储:

1)基本数据类型的存储原理:所有的简单数据类型不存在“引用”的概念,基本数据类型都是直接存储在内存中的内存栈上的,数据本身的值就是存储在栈空间里面,而Java语言里面八种数据类型是这种存储模型;

2)引用类型的存储原理:引用类型继承于Object类(也是引用类型)都是按照Java里面存储对象的内存模型来进行数据存储的,使用Java内存堆和内存栈来进行这种类型的数据存储,简单地讲,“引用”是存储在有序的内存栈上的,而对象本身的值存储在内存堆上的;

区别:基本数据类型和引用类型的区别主要在于基本数据类型是分配在栈上的,而引用类型是分配在堆上的(需要java中的栈、堆概念),

基本类型和引用类型的内存模型本质上是不一样的。

例1:我们分析一下”==“和equals()的区别。

首先,我定以两个String对象

Stringa="abc";

Stringb="abc";

然后

if(a==b){

System.out.println("a==b");

}else{

System.out.println("a!=b");}

程序输出a!=b

原因:a和b的地址是不相同的,a==b比较的是两个变量的地址

例2:定义两个基本类型

int a=4;

int b=4;

if(a==b){System.out.println("a==b");}

else

{System.out.println("a!=b");}

输出:a==b

原因:==比较的是两个变量的内容

猜想:不论是基本数据类型还是引用类型,他们都会先在栈中分配一块内存,对于基本类型来说,这块区域包含的是基本类型的内容;而对于对象类型来说,这块区域包含的是指向真正内容的指针,真正的内容被手动的分配在堆上。

4.对象引用
(可自行搜索)

Java基础常考点–Map
能考查到数据结构,java的基础实现以及对并发问题的处理思路的掌握程度.
一、HashMap
通过数组加链表实现.
数组中的元素为一个链表,通过计算存入对象的hashcode,确认存入位置,用链表解决散列冲突.链表的节点存入的是键值对.

填充因子的作用
Map扩容的rehash机制
容量是二的幂次方.
是为了方便按位与操作计算余数,比求模更快
多线程风险的原因
对线程put时,会在超过填充因子的情况下rehash.HashMap为避免尾部遍历,链表插入采用头插法,多线程场景下可能产生死循环.

二、ConcurrentHashMap
分段锁思想
1.7中采用segment分段加锁,降低并发锁定程度.
CAS自旋锁
1.8中采用CAS自旋锁(一种乐观锁实现模式)提高性能.但在并发度较高时,性能一般.
红黑树
1.8引入红黑树解决hash冲突时的链表查找问题.在链表长度大于8且总容量大于64时启用.扩容后链表长度小于6时重新转为一般链表.(8,6,64为默认参数)

Java版本特性
1.8
* Lambda表达式
* StreamAPI
* 方法引用
* 接口默认方法
* Metaspace替换PremGen

1.9-1.10
* 模块系统
* 默认G1回收器
* 接口私有方法
* 局部变量判断
* Graal编译器

1.11
* ZGC
* 字符串API增强
* 内建HTTP Client

面试考察点
1.实现方法和使用方式
* HashMap在JDK1.8中的实现方式

扩容就是将旧数组的元素移动到新数组

1、HashMap底层是用数组+双向链表+红黑树实现的
2、插入元素的时候,首先通过一个hash方法计算得到key的哈希值,进而计算出待插入的位置
3、如果该位置为空,则直接插入(包装成Node)
4、如果该位置有值,则依次遍历。比较的规则是,hash值相同,key值相等的元素视为相同,则用新值替换旧值并返回旧值。
5、如果该位置的元素是红黑树结构,则同理,查找,找到则替换,没找到则插入。

划重点:
JDK1.8中HashMap与JDK1.7中有很多地方不一样
1、1.8中引入了红黑树,而1.7中没有
2、1.8中元素是插在链表的尾部,而1.7中新元素是插在链表的头部
3、扩容的时候,1.8中不会出现死循环,而1.7中容易出现死循环,而且链表不会倒置

2.实际应用中容易犯错的点
* ==与equals区别是什么

"=="和equals方法究竟有什么区别?
(单独把一个东西说清楚,然后再说清楚另一个,这样,它们的区别自然就出来了,混在一起说,则很难说清楚)

==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符。
如果一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存,例如Objet obj = newObject();变量obj是一个内存,new Object()是另一个内存,此时,变量obj所对应的内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,即要看这两个变量所对应的内存中的数值是否相等,这时候就需要用==操作符进行比较。

equals方法是用于比较两个独立对象的内容是否相同,就好比去比较两个人的长相是否相同,它比较的两个对象是独立的。例如,对于下面的代码:
String a=new String("foo");
String b=new String("foo");

两条new语句创建了两个对象,然后用a/b这两个变量分别指向了其中一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值是不相同的,所以,表达式a==b将返回false,而这两个对象中的内容是相同的,所以,表达式a.equals(b)将返回true。
在实际开发中,我们经常要比较传递进行来的字符串内容是否等,例如,String input = …;input.equals(“quit”),许多人稍不注意就使用==进行比较了,这是错误的,随便从网上找几个项目实战的教学视频看看,里面就有大量这样的错误。记住,字符串的比较基本上都是使用equals方法。
如果一个类没有自己定义equals方法,那么它将继承Object类的equals方法,Object类的equals方法的实现代码如下:
boolean equals(Object o){
return this==o;
}

这说明,如果一个类没有自己定义equals方法,它默认的equals方法(从Object类继承的)就是使用==操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回false。如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖equals方法,由你自己写代码来决定在什么情况即可认为两个对象的内容是相同的。
-----------------------------------------------------------------
简单的说,==比较两个人是否究竟是真正同一个人,equals一般用来比较两个人在逻辑上是否相等(比如规定两人成年之后身高相同就算两人相同等等),想怎么定义就怎么定义,如果不覆盖equals方法的话,默认仍然是比较两人是否同一个人(废话,两个人都还处于胚胎状态,都没有具体特征,怎么可能在逻辑上比较)。

* 对象强引用使用不当会导致内存泄露,考察不同引用方式和作用的理解
解决刚说的内存泄露问题,主要运用的就是显式声明引用的类型,首先简单解释下相关的知识:

 1、引用的类型:强,软,弱。普通的java引用,也是我们最一般的java引用对象,便是强引用,它直接影响垃圾回收的进行(有强引用指向对应的对象,GC便不可回收该对象,即使内存不够用);软引用,和强引用的主要区别是:它会影响GC对对象的回收工作,但是,当虚拟机的内存不够用时,软引用所指向对象(当然,不能同时有强引用指向对象)会被强制回收;弱引用就等级更低,它无法影响GC对对象的垃圾回收工作,只能引用并访问对象。具体三种引用可以由下面的代码例子说明:

//软引用和弱引用的使用例子
public void referenceExam(){
Object object = new Object();//这个普通object引用就是一个强引用
//软引用通过SoftReference创建一个软引用
SoftReference<Object> softObjReference = new SoftReference<Object>(object);
//通过get方法获取真正的对象引用
softObjReference.get();
//弱引用通过WeakReference来关联一个对象
WeakReference<Object> weakObjReference = new WeakReference<Object>(object);
weakObjReference.get();//这个方法返回了真实的对象引用,当没有强引用或者弱引用指向它时,返回为null

}
  
2、对于防止内存泄露以及与垃圾回收有关的引用强弱类型,我们可以归纳出下面的特点:
  A、当我们在高速缓存中缓存较大的对象例如缓存图片等以提高读取速度的时候(针对大内存对象问题),可以将相关的对象设置为软引用对象,这样保证在内存不够用的时候GC可以进行回收工作。
  B、当我们完全不像由于当前对对象的引用而影响对象的其他模块原来设定的GC回收时期,我们可以采用弱引用(相当于只可访问数据而访问不会对GC对对象的回收造成影响)
  C、当然,java还有一种叫做虚引用的引用类型变量,该变量其实现实中用得不多,主要用来跟踪对象GC过程,所以这里不详细讲。
最后,至于什么时候要设置对象为弱引用(或者软引用),个人觉得还是要根据具体的业务进行对象使用的判断,如果全局对象过大,有可能在程序中造成泄露问题,或者说我们不想在不清楚对象何时可以被回收(工厂通过接口提供对象给客户)时,可以采用软引用或者弱引用进行对象访问。

以反例来描述实际场景中误用的危害.
如,大量使用反射会影响性能.

与知识点相关的最新技术趋势.
如,讲到ConcurrentHashMap,可以介绍1.8的改进细节.

真题汇总
一、Object中的equals和hashcode的作用分别是什么?
1 这两个方法都是来自java.lang.Object类,在Object中hashCode()返回的是对象的地址值,equals()方法是对两个对象的地址进行的比较;如果equals()方法的返回值相同,说明两个对象的地址值也是相同的,所以hashCode()的返回值也是相同的。

2在向集合(如HashSet,TreeSet等)中添加元素的时候遵循的规则是:
A 判断对象的hashCode的值是否相同,如果不相同,认为这两个元素不相同,如果相同,转入B。
B判断两个对象的equals运算的值是否相同,如果不相同,认为两个对象是不相同的,
如果相同认为两个对象是相同的。

3 在向封装类的对象中添加元素的时候,由于封装类已经重写了hashCode()和equals()方法,
所以这里使用的是封装类自己重写的两个方法。所以只要存入的内容相同就认为是相同的对象。

4 向集合中添加自定义类的对象时,如果自定义类没有重写equals()和hashCode()方法,就会调用Object的这两个方法,也就是hashCode()方法产生一个hashCode值(永远不会相同的地址),再使用equals()方法进行比较(地址);所以可能会产生向集合中添加已有的对象的时候,由于两次产生的hashcode值是不同的,equals()方法认为这两次添加的不是相同的元素,从而造成了集合对象中有重复的元素出现。解决的方法是:重写自定义类的这两个方法。

5 hashCode()方法经常和散列集合一起使用(HashSet,HashMap,HashTable),
如果集合中不允许有重复的元素,如果采用equals()进行比较的话,会产生效率问题。
所以使用hashCode()方法,在添加元素的时候就进行保证元素的唯一性。
6 如果一个类重写了equals()方法,则一定也要重写hashCode()方法,原因是:虽然equals()方法重写可以保证正确判断两个对象在逻辑是否相同,但是hashCode()方法映射的物理地址是不相同的,依然会将逻辑上相同的两个元素存入集合,但是第二个对象的内容会是Null.

二、final,finally,finalize的区别与使用场景
(1)final:可以作为修饰符修饰变量、方法和类,被final修饰的变量只能一次赋值;被final修饰的方法不能够在子类中被重写(override);被final修饰的类不能够被继承。
 (2)finally用在异常处理中定义总是执行代码,无论try块中的代码是否引发异常,catch是否匹配成功,finally块中的代码总是被执行,除非JVM被关闭(System.exit(1)),通常用作释放外部资源(不会被垃圾回收器回收的资源)。
 (3)finalize()方法是Object类中定义的方法,当垃圾回收器将无用对象从内存中清除时,该对象的finalize()方法被调用。由于该方法是protected方法,子类可以通过重写(override)该方法以整理资源或者执行其他的清理工作。(有可能对象会复活)

三、简单表述一下Java的异常机制
Java异常机制主要依赖于try、catch、finally、throw、throws五个关键字。

1.try:它里面放置可能引发异常的代码

2.catch:后面对应异常类型和一个代码块,用于表明该catch块用于处理这种类型的代码块,可以有多个catch块。

3.finally:主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件),异常机制总是保证finally块总是被执行。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者 throw等终止方法的语句,则就不会跳回执行,直接停止。

4.throw:用于抛出一个实际的异常,可以单独作为语句使用,抛出一个具体的异常对象。

5.throws:用在方法签名中,用于声明该方法可能抛出的异常。

Java的异常分为两种,checked异常(编译时异常)和Runtime异常(运行时异常)

1. java认为checked异常都是可以再编译阶段被处理的异常,所以它强制程序处理所有的checked异常,而Runtime异常无须处理,java程序必须显式处理checked异常,如果程序没有处理,则在编译时会发生错误,无法通过编译。

2. checked异常体现了java设计哲学:没有完善处理的代码根本不会被执行,体现了java的严谨性,

四、线上使用的那个版本jdk,为什么使用这个版本(有什么特色)?

java之语言的更多相关文章

  1. Notes 20180506 : Java程序设计语言概述

    2.Java程序设计语言概述 如果对于开发语言的排行榜有所关注的话,那么会发现很长一段时间以来Java都是位居榜首的高级开发语言,作为一个Java开发者,为此感到骄傲的同时也深感忧虑,骄傲的是自己接触 ...

  2. JAVA在语言级支持多线程

    进程:任务 任务并发执行是一个宏观概念,微观上是串行的. 进程的调度是有OS负责的(有的系统为独占式,有的系统为共享式,根据重要性,进程有优先级). 由OS将时间分为若干个时间片. JAVA在语言级支 ...

  3. Java程序语言的后门-反射机制

    在文章JAVA设计模式-动态代理(Proxy)示例及说明和JAVA设计模式-动态代理(Proxy)源码分析都提到了反射这个概念. // 通过反射机制,通知力宏做事情 method.invoke(obj ...

  4. java笔记--java的语言特性

    java的语言特性 1.简单性:例如:java不再支持多继承,而c++是支持多继承的,多继承比较复杂. c++中有指针,java中屏蔽了指针的概念.所以相对来说比较简单. //注:java语言的底层是 ...

  5. C/C++/Java/C#语言的基本类型

    C语言的基本类型有:char, short ,int ,long ,float ,double 一共6种基本类型. C++语言有:bool, char ,wchar_t, short, int , l ...

  6. java发展史与java的语言特性

    概述: Java 体系比较庞杂,功能繁多,这也导致很多人在自学 Java 的时候总是感觉无法建立 全面的知识体系, 无法从整体上把握Java 的原因. 在这里我们先简单了解一下Java 的版本. 具体 ...

  7. Java 国际化 语言切换

      Java国际化 我们使用java.lang.Locale来构造Java国际化的情境. java.lang.Locale代表特定的地理.政治和文化.需要Locale来执行其任务的操作叫语言环境敏感的 ...

  8. Java描述语言、国家和地理的类——Locale

    Locale类代表一个特定的地理.语言和国家环境.一个Locale的实例对象本身不会验证它代表的语言和国家地区信息是否正确,只是向一些对国家和语言.地理等比较敏感的类提供国家地区语言信息,这些类有Da ...

  9. java安全性语言

    java通过所谓的沙箱安全模型保证了其安全性,以下我们就来看看java提供的安全沙箱机制. 组成沙箱的基本组件例如以下: 1.类装载器结构: 2.class文件检验器: 3.内置于java虚拟机(及语 ...

  10. 分析Java因为语言慢

    Java在早期的(例JDK1.2一旦)这是很慢.也许是因为有很多的优化,以提高装置的版本号,Java这是越来越快,所以这是现在非常的Java和C/C++什么什么慢速争议. 我想我自己的理解.谈论的影响 ...

随机推荐

  1. talend工具通过关键字来取得text文本中的数据

    问题描述: 在文件夹中有多个text文本,通过关键字来取得text文本里面我所需要的数据,并出力到Excel里面.取得的数据,在text文本里面可能是多行的存在,并且在Excel里面是一行的存在. 解 ...

  2. 什么是SSH 以及常见的ssh 功能

    什么是SSH? 简单说,SSH是一种网络协议,用于计算机之间的加密登录.如果一个用户从本地计算机,使用SSH协议登录另一台远程计算机,我们就可以认为,这种登录是安全的,即使被中途截获,密码也不会泄露. ...

  3. 使用 IDEA 创建 maven 项目

    文章目录 第一步 第二步 第三步 目录结构的设置 看下 web.xml 配置文件 第一步 点击 maven : 勾选从模板创建 : 选择 webapp : 第二步 第三步 如果你自己对 maven 进 ...

  4. 更改CodeBlocks注释的颜色

  5. JVM Java 内存区域透彻分析(转)

    出处:  Java 内存区域透彻分析  Java8内存模型—永久代(PermGen)和元空间(Metaspace) 这篇文章主要介绍Java内存区域,也是作为Java虚拟机的一些最基本的知识,理解了这 ...

  6. pause的作用

    重要概念:Pod内的容器都是平等的关系,共享Network Namespace.共享文件 pause容器的最主要的作用:创建共享的网络名称空间,以便于其它容器以平等的关系加入此网络名称空间 pause ...

  7. uboot 与 代码重定位

    ref: https://blog.csdn.net/dhauwd/article/details/78566668 https://blog.csdn.net/yueqian_scut/articl ...

  8. 通过pip命令导出和导入Python环境安装包

    我们在开发完代码后,一般需要将依赖包导出,然后在移植到其他系统使去安装,保证环境正常   导出Python环境安装包[root@bogon ~]# pip freeze > packages.t ...

  9. 一个因MySQL大小写敏感导致的问题

    做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 00 MYSQL对大小写敏感 见字如面,见标题知内容.你有遇到过因为MYSQL对大小写敏感而被坑的体验吗? 之前看过阿里巴 ...

  10. vue 集成 vis-network 实现网络拓扑图

    vis.js  网站 https://visjs.org/ vs  code 下安装命令 npm install vis-network 在vue  下引入 vis-network组件 const v ...