Java基础记录(一)

190 阅读6分钟

1. 面向对象:

a.封装:

javaBean\orm 外部无需关心内部实现

b.继承:

继承基类方法,做出自己的扩张/改变

c.多态:

继承、方法重写、父类引用 父类类型 变量名 = new 子类对象; 变量名.方法名(); 无法调用子类方法

2. JDK、JRE、JVM三者区别和联系

a. JDK:

java 开发工具

b. JRE:

环境

c. JVM:

虚拟机

3. == 和 equals

a. == :

对比的是栈中的值,基本数据类型是变量,引用类型是堆中内存对象的地址

b. equals:

object 中默认也是采用==比较 Object

public boolean equals(Object object){
 	return (this==obj);   
    
}

String

public boolean equals(Object anObject){
 if(this == anObject){
  return true;   
 }
 if(anObject instanceof String){
   String anotherString = (String)anObject;
   int n = value.length;
   if(n == anotherString.value.length){
       char v1[] = value;
       char v2[] = anotherString.value;
       int i =0 ;
       while(n--!=0){
        if(v1[i]!=v2[i])return false;
        i++;
       }
       return true;
   }
 }
 return false;
    
}

4. final

修饰类 修饰方法 修饰变量 内部类/外部类变量问题

5.String、StringBuffer、StringBuilder

String是final修饰的,不可变,每次操作都会产生新的String对象 StringBuffer和StringBuilder都是在原对象上操作 StringBuffer是线程安全的,StringBuilder是线程不安全的 StringBuffer方法是synchronized修饰的 性能:StringBuilder>StringBuffer>String

6. 重载和重写的区别

a. 重载

发生在同一个类中,方法名必须相同,参赛类型不同,个数不同,顺序不同方法返回值和修饰符不同,发生在编译时。

b. 重写

发生在父子类中,方法名和参数列表必须相同,返回值范围小于等于父类,抛出异常范围小于等于父类,访问修饰范围大于父类。如果父类方法修饰词为private,子类不能重写

7. 接口和抽象类的区别

a. 接口:

只能存在public abstract方法 可以实现多个。 接口成员变量只能是public static final类型 bird like aircraft 能做什么

b.抽象类:

可以存在普通成员函数, 抽象类只能继承一个, 成员变量可以是各种类型 不允许实例化 BWM is a 是什么

8. List和Set区别

a.List

有序可重复有下标访问

b.Set

无序不可重复只能通过iterator遍历访问

9.hashCode和equals

a. hashCode

获取哈希吗,散列码,返回int型整数,哈希表索引,java中的任何类都包含hashCode(),散列表存储的是key-value , 快速找到键对应的值 对象加入HashSet,HashSet会计算对应的hashCode是否有值,没有则加入,有则无法加入重新散列其他位置,大大减少equals的次数,大大提高执行速度 HashSet中算法:两个不一样的值会计算出相同hashCode。 (1)如果两个对象相等,则hashcode一定相同

b. equals

要去比较内存地址 两个对象有相同的hashCode值,他们也可能不相等

10. ArrayList和LinkedList区别

a.ArrayList

动态数组,连续内存存储,适合下标访问(随机访问),类型一致,非常快,占有内存长度相同 扩容机制:建一个新的数组 old new[10] --> new [15] ,老数组数据copy到新数组 静态数组 new int[10]

尾部插入指定初始容量可以极大提升性能,甚至超过linkedList (创建item,消耗小)

b.LinkedList

链表 可以存储在分散内存,适合做数据插入和删除,不适合查询; 需要逐一遍历,必须使用iterator不能使用for循环。因为每次for 插入,需要创建大量的node (性能消耗在创建node对象) for循环效率很低,对下标访问不友好,需要重新遍历 不要试图使用indexOf等返回元素索引,需要对list进行遍历,当结果为空时,会遍历整个列表

11. HashMap 和HashTable的区别,底层实现是什么

a. HashMap

没有synchronized修饰 线程不安全 允许key,value为null

b. HashTable

有syn 线程安全的,效率很低 不允许key/value为null

c.HashMap实现

底层原理:

数组+链表实现,数组长度为2的幂 jdk8 :链表高度到8,数组长度超过64,链表转变为红黑树(平衡二叉树),元素以内部类node节点存在 · 计算key hash值,二次hash然后对数组长度取模,对应到数组下标; · 如果没有产生hash冲突(下标位置没有元素),则直接创建node存入数组 · 如果产生冲突,先进行equals比较,相同则取代该元素,不同则判断表高度插入链表,链表高度达到8并且数组长度达到64则会转变为红黑树,长度低于6则将红黑树转回链表 · key为null,放到下标为0的位置

数组扩容:

数组定义静态的,长度固定,hashMap可以一直放值小于定义值,超过定义的范围,根据扩容因子会重新创建新数组,然后copy进新数组,完成扩容。

12.ConcurrentHashMap原理,jdk7和8的区别

a. jdk7:

数据结构:ReentrantLock+Segment+HashEntry数组(里面链表),一个segment包含一个HashEntry,每个HashEntry又是一个链表。 元素查询:二次hash,第一次hash定位到Segment,第二次hash定位到元素所在的链表头部 锁:Segment分段锁 Segment继承了ReentranLock,锁定操作的Segment,其他的Segment不受影响,并发度为segment个数,可以通过构造函数指定,数组扩容不会影响其他的segment。 get方法无需加锁,volatile保证的。

b. jdk8:

数据结构:

synchronized (hash扩容)+ CAS (乐观锁)+ Node + 红黑树,Node的val和next都用volatile修饰,保证可见性查找,替换,赋值操作是CAS。

锁:

锁链表的head节点,不影响其他元素的读写,锁的力度更细,效率更高,扩容时会阻塞所有的读写操作,因为当前为并发扩容

读操作无锁:

Node的val和next使用volatile修饰,读写线程对该变量互相可见 数组用volatile修饰,保证扩容时被读线程感知

13. 如何实现一个IOC容器

a.配置文件配置包扫描路径

b.递归包扫描获取.class文件

c. 反射、确定需要交给IOC管理类

d. 对需要注入的类进行依赖注入

详细描述: 配置文件中指定需要扫描的包路径 定义一些注解,分别表示访问控制层,业务服务层,数据持久化层,依赖注入注解,获取配置文件的注解 从配置文件中获取需要扫描的包路径,获取到当前路径下的文件信息及文件夹信息,我们当前路径下所有以.class结尾的文件添加到一个Set集合中进行存储。 遍历set集合,获取在类上有指定注解类,并将其交给IOC容器,定义一个安全的Map用来存储这些对象 遍历IOC容器,获取每一个类的实例,判断里面是否有依赖其他类的实例,然后进行递归注入