第二--java基础

java基础

java基础目录

面向对象基础


1.String 、StringBuilder 、StringBuffer 的区别?

1.String是制度字符串,引用的字符内容是不能被改变的
String底层维护的char[]数组,使用final修饰。既然使用final修饰,无法重给他赋值;String中的方法,替换,拼接,子串等都是返回一个新的字符串
StringBuffer和StringBuilder底层维护的char[]数组,没有使用final修饰,方法都是在原来对象字符数组的基础上进行操作,不会产生新的对象;
2.StringBuilder和StringBuffer表示的字符串对象可以直接被修改
如果不经常改变字符串的值,拼串操作;使用String;
如果有拼接字符串的需求:
没有线程安全使用StringBuilder
有线程安全没StringBuffer
3.StringBuilder单线程环境下作用, 所以相对于StringBuffer效率更高. StringBuffer加了锁, 相对更安全
StringBuffer所有的方法都使用synchronized进行修饰,线程安全;
String是不可变的字符串,线程安全
StringBuilder线程不安全


2.equals() 与 == 的区别?

1.==用来比较值是否相等
2.equals用在基本数据类型则比较值是否相等
3.equals直接调用类比较, 则是比较地址


3.是否可以继承String类? 为什么用final修饰?

不能, String类被final修饰不能被继承
为了安全和效率
1.只有字符串是不可变的, 字符串常量池才有可能实现
2.只有字符串是不可变的, 多线程下才能安全, 同一个字符串实例可以被多个线程共享
3.因为字符串不可变, 所以在被创建的时候就已经被hashcode缓存了, 不需要重新计算, 使得字符串很适合做map中的键


4.什么是面向对象编程 ?

面向对象编程的基本思想就是利用封装继承和多态等概念进行程序设计,
从现实世界中实际存在的事物(对象)出发来构造软件系统
尽可能的运用人类的自然思想进行程序设计


5 面向对象的三大特征

封装: 将事物的属性和行为抽取出来封装到类中
继承: 子类继承父类可以实现代码的抽取和复用, 单继承, 多实现
多态: 父类的引用指向子类的实现 Animal a=new Dog(); 三个条件 继承 重写向上转型


6.JDK,JRE,JVM

JDK是开发者工具包, 包含jre和JVM
JRE是开发环境, 包含JVM和核心类库
JVM是虚拟机


7.java基本数据类型

整数型: byte 1 short 2 int 4 long 8
浮点型 float 4 double 8
字符型 char 2
布尔型 boolean 4


8.为什么要提供包装类?

包装类作为基本数据类型对应的引用数据类型,方便了涉及到对象的操作;
包装类中提供了对应基本数据类型最大值,最小值等属性,及相关方法


9.什么是方法签名

方法名称和参数类型


10.java中的访问修饰符

private 私有权限 不同包非子类
default 默认 不同包子类
protect 包权限
public 公共权限


11.final有什么用?和finally,finalize有什么区别?

final修饰的类不能被继承 final修饰的方法不能被重写 final修饰的变量为常量, 不能被重新赋值
finally 一般用在try-catch结构中, 不管是否出现异常, finally后面的语句都会被执行
finalize 是Object类的方法 用在垃圾回收器中


12.this和super的区别

this指向的是自身的一个对象, 代表对象本身,
super指向的是自己的一个超类对象, 这个超类对象是最近的一个父类
this()调用的是本类的其他构造方法
super()调用的是父类的构造方法


13.break ,continue ,return 的区别及作用?

break 跳出循环
continue 结束当前循环进入下一循环
return 结束整个方法


14.抽象类能被final修饰吗?

不能, final修饰的类不能被继承 而抽象类本身就是用来被继承的


15.static修饰的方法能调用非static修饰的变量和方法吗 ?

static修饰的方法只能调用静态的变量和方法


16.局部内部类和匿名内部类访问局部变量的时候,为什么变量必须要加上final?

因为生命周期不一样 局部变量保存在栈内存中 当方法结束后 非final修饰的变量就会被销毁 而局部内部类对局部变量的引用仍然存在 调用局部变量的时候就会出错


17.重载(Overload)和重写(Override)的区别

重载: 方法名称相同 参数类型不同 或者参数数量不同 参数顺序不同
重写: 发生在父类中 方法的名称参数必须相同 跑出的异常小于父类 访问修饰符大于等于父类


18.构造器(constructor)是否可被重写(override)

构造器不能被继承 所以不能重写 但是可以被重载


19.Java中创建对象的方式有哪些

1 使用new关键字
2 使用Class类的newlnstance方法
3 使用Constructor类的newlnstance方法
4 使用clone方法
5 使用反序列化


20.构造器代码块、局部代码块、静态代码块执⾏顺序和执⾏次数?

①执行顺序:
静态代码块:
当类加载的时候执行,
如果类中有多个静态代码块,按照书写顺序执行
构造器代码块:
对象被创建(任意构造方法执行)之前执行,优先于构造方法,
如果类中有多个构造代码块,按照书写顺序执行
局部代码块:
当方法执行的时候执行
如果方法有多个局部代码块,按照顺序执行
②执行次数:
静态代码块:一次
构造器代码块:每次创建对象都会执行
局部代码块:每次调用方法都会执行


21.构造代码块的作⽤?

① 可以把所有的构造方法公共的代码放在构造代码块中
②匿名内部类的初始化操作,匿名内部类没有明显的构造方法


22.Integer缓存区间?什么时候触发缓存区间?

① Integer缓存区间:
在Integer类中定义了一个内部类
在IntegerCache中维护了一个Integer数组:[-128,127]范围的Integer实例
②什么时候触发缓存区间?
基本数据类型转化为包装类型的时候,如果基本数据类型范围[-128,127]从数组中返回Integer实例,否则创建Integer实例


23.String str = “abc” 和 String str = new String(“abc”)区别?

①String str = “abc” :
1.如果常量池中没有"abc",在常量池中创建"abc"
2.str指向常量池"abc"
②String str = new String(“abc”):
1.如果常量池中没有"abc",在常量池中创建"abc"
2.在堆中创建对象,将常量池中"abc"复制到堆中
3.str指向堆中对象


24.&和&& | || 区别是什么?

①& |:即可以作为逻辑运算符又可以作为位运算符
②&& ||:只能作为逻辑运算符
③ & |作为逻辑运算符和&& ||作为逻辑运算符的区别:&& || 有短路效果,当有多个表达式时,左边的表达式值可以确定结果时,就再继续运算右边的表达式的值


25.JDK1.8之后有哪些新特性?

1.lambda表达式
2.stream
3.接口增强
4.并行数组排序
5.Optional
6.新的时间和日期的API
7.可重复注解


26.Java中深克隆和浅克隆的区别?怎么实现?

①区别
浅克隆:
原对象中为基本数据类型的属性值克隆给克隆对象
原对象中为引用数据类型的引用值克隆给克隆对象
源对象和克隆对象中引用类型的属性指向的是同一个对象
深克隆:
原对象和克隆对象引用数据类型的属性指向不是同一个对象
②如何实现

@Data
public class Person {
    private int id;
    private Address addr;
}

@Data
class Address {
    private int id;
    private String city;
} 

浅克隆

对Person对象进行Clone
1.要求实现Cloneable标识性接口(标记该类的对象可以被clone)
2.重写Object 中clone方法
	@Data
public class Person implements Cloneable {
    private int id;
    private String name;
    private Address addr;

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

@Data
class Address {
    private int id;
    private String city;
}

protected native Object clone() throws CloneNotSupportedException;
测试
Person person = new Person();
person.setId(1);
person.setName("张三");
Address address = new Address();
address.setId(2);
address.setCity("西安");
person.setAddr(address);

Person clone = (Person) person.clone();
System.out.println(person.getAddr() == clone.getAddr());

深克隆

利用IO读写;
@Data
public class Person implements Cloneable, Serializable {
    private int id;
    private String name;
    private Address addr;

    @SneakyThrows
    @Override
    public Object clone() throws CloneNotSupportedException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream bos = new ObjectOutputStream(byteArrayOutputStream);
        bos.writeObject(this);
        byte[] bytes = byteArrayOutputStream.toByteArray(); //对象的字节数据
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        ObjectInputStream bis = new ObjectInputStream(byteArrayInputStream);
        Object object = bis.readObject();
        bos.close();
        bis.close();
        return object;
    }
}

@Data
class Address implements Serializable{
    private int id;
    private String city;
}
@Data
public class Person implements Cloneable {
    private int id;
    private String name;
    private Address addr;

    @Override
    public Object clone() throws CloneNotSupportedException {
        String json = JSON.toJSONString(this); //将源对象转化为JSON字符串
        return JSON.parseObject(json,Person.class);
    }
}

@Data
class Address {
    private int id;
    private String city;
}

27.Comparable 和Comparator的区别,分别说出使⽤场景?

区别:
①排序逻辑:
Comparable排序逻辑必须在待排序元素的类中,也称为自然排序
Comparator排序的逻辑写在另一个类中实现,也称为比较器排序
②排序方法:
int compareTo(E o1)
int compare(E o1,E o2)
③接口所在包:
java.lang.Comparable
java.util.Comparator
使用场景:
TreeMap&TreeSet: TreeSet
Collections.sort(List list)
Collections.sort(List list,Comparator comparator)


28.Object类和范型的区别,说出范型的执⾏机制,为什么要使⽤范型?

①Object类和泛型的区别:
public Object doSomething(Object obj) {…}
public T doSomething(T t) {…}

如果从方法调用的角度,没有什么区别

eg:如果调用第一个方法,传递String,返回String,需要将返回的Object强转为String
String newFoo = (String) my.doSomething(foo);

eg:如果调用第二个方法,传递String,返回String
String newFoo =my.doSomething(foo);

②为什么使用泛型?:
不需要做强制类型转换

编译时自动检查类型安全。如果使用Object类的话,你没法保证返回的类型一定是String,也许是其它类型。这时你就会在运行时得到一个类型转换异常

③泛型的执行机制?:
泛型的本质是一种参数化类型也就是将数据类型作为参数传递,其中T相当于形式参数负责占位,而真正传递的数据类型String相当于实际参数;用于给形式参数T进行赋值;从而使所有T都被替换为String;由于实际参数可以传递各种引用类型,因此叫泛型


29.Error 和Exception 有什么区别?

①、从继承体系:Error和Exception都是Throwable的子类
②、从功能来说:Error是程序无法处理的异常、Exception是程序可以处理的异常


30.什么是反射?

①反射是为了动态加载一个类,动态调用一个方法,动态访问一个属性 这些动态要求设计的;
②JVM会为每一个类创建一个java.lang.Class的实例,通过该对象就可以获取该类的信息,然后通过java.lang.reflect包下的API达到各种动态要求


31.设计模式

创建型模式:提供了对象创建过程中的各种问题的解决方案总结
单例模式、抽象工厂模式、原型模式、构建者模式、工厂方法模式

结构性模式:对类在设计上的总结,比较关注类继承,组合关系。
代理模式:静态代理,动态代理;适配器模式;桥接模式;装饰者模式;外观模式;享元模式;组合模式

行为型模式:对象直接的交互和职责划分总结
观察者模式、模板模式、策略模式、职责链模式、迭代器模式、状态模式、访问者模式、备忘录模式、命令模式、解释器模式、中介模式。



集合


1.ArrayList和LinkList的区别?

ArrayList查询速度快(不准确),尾部增删快,头部增删慢,随机访问速度快;LinkList头尾增删速度快,中间不高,性能远比arraylist差,不适合做查询;真想查询用hashMap
①是否保证线程安全: ArrayList 和 LinkedList 都不保证线程安全;
②底层数据结构: Arraylist 底层使用的是数组, 采用动态扩容机制;LinkedList 底层使用的是双向非循环列表;
③插入和删除是否受元素位置的影响:
ArrayList 在内存中是连续的储存单元, 所以在中间删除|插入元素比较慢, 尾部却很快
LinkedList 采用双向非循环链表存储,所以插入,删除元素时间复杂度不受元素位置的影响。
④是否支持快速随机访问 : LinkedList 不支持高效的随机元素访问,ArrayList 实现了RandmoAccess 接口,所以有随机访问功能
⑤内存空间占用:
ArrayList的空间浪费主要结尾会预留一定的容量空间
LinkedList的空间花费则体现在它的每一个元素都需要消耗比ArrayList更多的空间
⑥插入和删除的平均复杂度都为0(n),ArrayList根据索引查找的平均复杂度为0(1),linkedList为0(n)


2.HashMap底层原理

JDK8以前:数组+双链表
JDK8以后:数组+双链表+红黑树


3.HashMap的resize过程是什么样的

-采用hash表数据加链表的形式
-1.8以后引入了红黑树的数据结构 ,初始化数组长度为16
-当数组长度到0.75时扩容 , 链表长度大于8时转为红黑树 , 红黑树的长度小于6时转为链表结构
-数组中的元素容量超过了阙值的0.75就会触发扩容长度


4.HashMap你经常用在那个地方?

①电子商务的应用中使用HashMap作为缓存。
②金融领域出于性能的考虑非常多的运用HashMap和ConcurrentHashMap。
③controller层向前台返回数据可以用map封装数据
④mybatis中的map可以作为参数或者封装结果集


5.HashMap和Hashtable的区别?

1.hashMap去掉了HashTable 的contains方法,但是加上了containsValue()和containsKey()方法。
2.hashTable同步的,而HashMap是非同步的,效率上比hashTable要高。
3.HashMap允许null键和null值,hashTable不允许。
4.HashTable的线程安全的,HashMap线程不安全。


HashMap储存元素的流程

1.当时用put方法储存key vaule数据
2.首先会获取key的hashCode
3.对hashCode进行二次hash
4.对hash值取模数字的长度, 得到数组索引(桶下标)
5.将key value存入到指定索引的链表或者红黑树中
为什么要采用这种储存方案: 提高查找效率 时间复杂度可以达到0(1)


HashMap链表什么时候转化为红黑树

如果链表中储存的元素很多, 在进行存储和查找的时候效率比较低。1 2 3 4 他们的hash之都是九十七 桶大小是十六, 他们的同索引都是1;5 6 7 8 他们的hash值都是49 桶的大小是16, 他们的桶索引都是1
①对数组进行扩容
②数组扩容有可能解决不了问题:极端情况:如果存入的元素HashCode值都是一样,元素的桶索引一样
变成红黑树 红黑树添加 删除 查找效率O(logN)
数组长度>=64并且 链表长度超过树化阈值8


HashMap什么时候扩容

①capacity即数组容量,默认16
②loadFactor 加载因子,默认是0.75
③threshold 阈值。阈值-容量*加载因子
④当hashMap中元素个数超过阈值, 就会被触发扩容, 每次扩容一倍


HashMap桶中为什么不直接存放红黑树

①链表短的时候和红黑树性能差不多
②红黑树一个节点占用的内存要比链表一个节点占用的内存大(数据结构)
③如果hash值和随机,按照罗松分布,长度超过8的链表概率为0.00000006
红黑树防止恶意的DOS(Denial Of Service)攻击(伪造数据让数据的HashCode一样)


红黑树什么时候退化成链表

①数组扩容,导致树的拆分;并且拆分后<=6个
②红黑树元素被删除,如果根节点的左子树,右子树,左孙子,右孙子,有一个为null;再次删除一个节点,退化成链表


索引如何计算

①调用hashCode方法获取key的hashCode
②对hashCode在调用hashMap的hash方法进行二次hash运算
③最后使用hash %数组长度得到索引 注意:等价运算有个要求,数组长度必须2的n次方


HashMap数组长度为何是2的n次幂

①计算索引的时候,可以不用取模运算,采用位运算提高效率
②扩容的是时候hash &原始容量=0的时候留在源位置,否则新位置=原始位置+原始容量


HashMap在1.7和1.8添加元素的区别

1.7:元素采用头插入,元素的个数超过阈值并且没用空位置
1.8:
1.在第一次put的时候创建数组;
2.计算索引;
3.如果索引位置是null,创建Node(链表节点),存放到索引位置;
4.如果索引位置不是null,如果是TreeNode,走红黑树添加的逻辑,如果是Node,走链表添加的逻辑,如果链表长都超过8,走树化逻辑;
5.添加完毕偶判断元素的个数是否超过阈值,如果超过阈值,进行数组扩容


扩容因子为何是0.75

①大于该值节省空间,但是链表长度可能会比较长
②小于该值,扩容比较频繁,占用内存空间较大


多线程下操作hashMap会引发什么问题

1.8:数据丢失,后面添加的数据将前面添加的数据覆盖

6.List、Map、Set三个接口,存取元素时,各有什么特点?

List 有序可重复
Set 无序不重复
Map 一般都是键值对key-value值,value可多值


7.HashSet是如何保证元素唯一性的呢?

通过元素的两个方法 hashcode和equals来完成的
Map要求Key不能相同
1.通过key的hash值计算桶索引
如果桶索引位置没有元素,key一定不存在
2.判断添加的key是否和桶中元素key相同 : 添加key的hash和桶中元素hash是一样
不一样说明key不存在
一样, 进行equals判断 不一样不存在 一样则存在


8.HashCode的方法和作用

hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置

不同的对象可能会有相同的hashcode , 在比较一个对象是否相等时 , 首先需要比较对象的hashcode是否相等, 其次要比较equal是否相等

因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖 hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象 无论如何都不会相等


9.TreeSet怎么对集合中的元素进行排序?

TreeSet底层数据结构是二叉树。
1.让元素自身具备比较性,需要元素对象实现Comparable接口,覆盖compareTo方法
2.让集合自身具备比较性,需要定义一个实现了Comparator接口的比较器,覆盖compare方法


10.HashMap是线程安全的吗?如何得到一个线程安全的Map?

①HashMap线程不安全
②利用Collections工具类提供的synchronizedMap(map),利用装饰者设计模式,增强方法。
③使用ConcurrentHashMap


11.ConcurrentHashMap 的工作原理及代码实现

ConcurrentHashMap引入了分割(Segment)的概念,只对Map的一部分(Segment)进行上锁 , 这样 保证同步的时候,锁住的不是整个Map


12.map集合的两种取出方式?

1.通过map.keyset,先得到map集合的键,再根据键得到value值
2.通过map.entrySet直接得到键值对


13.Collection和Collections的区别?

Collection:
①是集合的顶级接口,定义了集合中统一的接口方法
②Collection接口有很多常用的实现类
③Collection的意义是为了具体的集合提供了最大化的统一操作方法
④其直接继承的接口有List和Set及Queue
Collections:
①集合的工具类
②提供了很多静态方法用于对集合元素进行排序,搜索及线程安全等操作


14.什么是链表

链表是可以将物理地址上不连续的数据连接起来,通过指针来对物理地址进行操作,实现增删改查 等功能。

链表大致分为单链表和双向链表:

-单链表:每个节点包含两部分,一部分存放数据变量的data,另一部分是指向下一节点的next指 针

-双向链表:除了包含单链表的部分,还增加的pre前一个节点的指针


15.链表的优缺点链表的优点

插入删除速度快(因为有next指针指向其下一个节点,通过改变指针的指向可以方便的增加删除元素)
内存利用率高,不会浪费内存(可以使用内存中细小的不连续空间(大于node节点的大小),并且在需要空间的时候才创建空间)
大小没有固定,拓展很灵活。

链表的缺点 : 不能随机查找,必须从第一个开始遍历,查找效率低


16.什么是红黑树

红黑树是一种含有红黑结点并能自平衡的二叉查找树。它必须满足下面性质:
性质1:每个节点要么是黑色,要么是红色。
性质2:根节点是黑色。
性质3:每个叶子节点(NIL)是黑色。
性质4:每个红色结点的两个子结点一定都是黑色。
性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。


17.常用的集合类有哪些?

Map接口和Collection接口是所有集合框架的父接口:

Collection接口的子接口包括:Set接口和List接口
Map接口的实现类主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap以及 Properties等
Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet等
List接口的实现类主要有:ArrayList、LinkedList、Stack以及Vector等


18.哪些集合类是线程安全的?

Vector:就比Arraylist多了个 synchronized (线程安全),因为效率较低,现在已经不太建议使 用。
hashTable:就比hashMap多了个synchronized (线程安全),不建议使用。
ConcurrentHashMap:是Java5中支持高并发、高吞吐量的线程安全HashMap实现。


19.如何实现数组和List之间的转化

①List转化为数组: toArray() T[]
②数组转化为List: Arrays.asList(T…t) List


20.ArrayList和Vector的区别

底层都是基于数组实现
①线程安全:
Vector是线程安全(synchronized), ArrayList不是, 如果需要一个线程安全的ArrayList,一般推荐CopyOnWriteArrayList
②扩容:
ArrayList扩容1.5倍
Vector默认扩容2倍


21.Queue中的peek()和poll()方法有什么区别

peek()查看队列头部元素
poll()出队


22.iterator和ListIterator的区别

①Iterator和 ListIterator都是迭代器接口, 不同的集合有不同的实现;ListIteretor是Iterator的子接口
②Iterator可以遍历List也可以遍历Set, 因为List和Set接口中都有 lterator iterator
③ListIterator不能遍历Set, 只有List接口中有 ListlteratorlistIterator()
④Iterator只能向后遍历(hashNext,next), ListIterator不仅可以向后遍历, 也可以先前遍历(hashPrevious, previous)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值