JAVA基础+JAVA集合

【JAVA基础】

【问】构造器(Constructor)就等于构造函数:

(1)只能重载,不能重写。

(2)this(...)表示此类的构造函数,super(...)表示父类的构造函数。他们都是为了解决构造方法中的代码冗余。

【问】abstract关键字冲突:final、static、private:  

(1)final和private修饰的方法不能被重写抽象方法就是为了重写,因此冲突;

(2)static是为了外部直接访问,但是abstract修饰成员没有方法体,所以访问没有意义,冲突。

【问】普通类和抽象类的区别?

 抽象类普通类
实例化不能
方法抽象方法(abstract)+ 实现方法实现方法(无抽象方法)

 

 

 

【问】接口和抽象类的区别?

 接口抽象类
设计思想层面行为抽象设计(像什么)模板抽象设计(是什么)
成员属性
常量(默认为static+ final  ,且只能通过接口访问)
不一定为常量,也不一定为静态。
成员方法

抽象方法(无修饰符,默认为public abstract)

抽象方法+实现方法

继承与实现角度可以多实现、多继承单继承

 

 

 

 

 

 

【问】强制类型转换?

多态情形下的,父类型转子类型。

class Person {
    public void eat() {
        System.out.println("The people were eating");
    }
}

class Boy extends Person {
    public void eat() {
      System.out.println("The boy were eating");
    }
}

public class Test {
    public static void main(String[] args) {
        Person person = new Boy();
        Boy boy = (Boy) person;
        boy.eat();
    }
}

【问】==、equals、hashCode?

(1)== :判断地址是否相同。

(2)equals:重写前,与“==”一样;重写后,判断内容(属性值)是否相同。

(3)hashCode:重写前,根据内存地址得到;重写后,根据内容(所有属性)得到。

【问】hashcode和equals的关系?为什么重写equals一定要重写hashcode?

涉及到这两个的未重写,都是在做自定义类、集合放置自定义对象的时候,一般java自带的类都是重写过的。

(1)

判断两个对象内容是否相等的过程:

中间多了一个hashcode的环节是为了减少equals的使用,hashcode比equals更快!

(2)

从两个点来回答这个问题:

(1)重写hashcode也是为了让hashcode派上用场,减少equals的使用。

(2)equals和hashcode不重写前都是根据内存地址得出的,重写后才能进行内容比较。如果不重写,hashcode就是根据内存地址得出的,当HashMap碰到两个地址不同,内容相同的对象,HashMap就会存入两个内容一样的键。

【问】什么是java中的值传递?java中方法对原始对象的影响总结?

(1)

 值传递引用传递(地址)
定义(java)将实际参数的地址复制一份,传递到函数中将实际参数的地址直接传递到函数中

能否修改原始对象的内容?

不能

 

 

 

 

(2)

  • java方法不能修改一个基本数据类型的参数(boolean、byte、short、int、long;char;float、double;)。
  • java方法可以改变一个对象或数组的状态。(数组就是一个对象)
  • java方法不能更改原对象的引用

【问】java中的异常了解哪些?Throwable类的方法?try-catch-finally?throw和throws?

(1)以下都是类,均代表异常的类型:

(2)

Throwable类的方法含义
getMessage()返回异常发生时的简要信息
toString()详细信息
getLocalMessage()本地化信息
printStackTrace()对象封装的异常信息

 

 

 

 

 

 

(3)try-catch-finally

++

finally不执行的四种情况:

(1)退出JVM的语句 System.exit(int) 

(2)finally代码块一进去就有异常 

(3)线程死亡

(4)CPU关闭

(4)

throw:

语句抛出异常,出现于函数内部,用来抛出一个具体异常实例;throw被执行后面的语句不起作用,直接转入异常处理阶段。

throws:

函数方法抛出异常,一般写在方法的头部,用来抛出一些异常,本身不进行解决,抛给方法的调用者进行解决(try...catch...)。

【问】什么是序列化?Java 序列化中如果有些变量不想进行序列化,怎么办?

(1)

序列化:

Java对象转换成字节流的过程。当 Java 对象需要在 网络上传输 或者 持久化存储 到文件中时,就需要对 Java 对象进行序列化处理。

反序列化:

将字节流转换成 Java 对象的过程。

(2)

对于不想进行序列化的变量,使用 transient 关键字修饰。(transient 只能修饰变量,不能修饰类和方法。)
 
transient 关键字的作用是:序列化时,阻止实例中那些⽤此关键字修饰的的变量序列化;当对象被反序列化时, 被 transient 修饰的变量值不会被恢复。
 

【问】什么是IO流?java IO流的种类?有了字节流,为什么还要字符流?

(1)

java数据想传输到别的地方(比如网络传输、持久化存储时),必须以IO流的形式(非java的数据形式有字节和字符。);传入java的流叫输入流,传出java的流叫输出流。“流”=数据传输的管道。

(2)

按照不同角色对流进行划分:

  1. 按照流的流向分:输入流,输出流

  2. 按照操作单元分:字节流,字符流(字节B/byte<字符)

  3. 按照流的角色:节点流、处理流。(目标设备中的类>>节点流>>处理流)

Java IO 流的 40 多个类都是从如下 4 个抽象类基类中派生出来的:

  • InputStream/Reader:所有输入流的基类(字节/字符)

  • OutputStream/Writer:所有输出流的基类(字节/字符)

按照操作方式分类结构图:

按操作对象分类结构图:

(3)

有了字节流,为什么还要字符流?(字符>字节)

虽然字节是传输的基本单位,但想要生成字节,需要通过JVM由字节转换,这个过程非常耗时,并且容易产生乱码;

所以,java的IO流直接设计出字符流,方便直接对字符进行流操作。

 字节流字符流
适用场景音频、图片等媒体文件涉及到字符的文件

 

 

 

【问】NIO和传统IO的区别(网络通信)?

 传统BIONIO
特点同步阻塞同步非阻塞(java4)
性能及原因性能较低;1个线程处理1个请求,线程在IO期间不能做别的事情(比如客户端没有数据发送给服务端,就一直等待)性能高;1个线程可以处理多个请求,线程在IO期间可以做别的事情(客户端没有数据发送过来,线程可以去做别的事情,性能高)
实现

基于Stream;

套接字:Socket、ServerSocket

基于Buffer+Channel,另外还有Selector选择器;套接字:SocketChannel、ServerSocketChannel

 

 

 

 

 

 

 

 

NIO模型的三大特点:

(1)channel:双向的,既可以读,也可以写。

(2)buffer:缓冲,是一块内存。

(3)selector:selector监测管道是否有数据变化(事件),在别的未获取锁的且有数据变化的线程中,提前把数据写入buffer或把数据从buffer中取出。

【问】static,this,super关键字?

static:

  1. 修饰成员属性和成员方法: 被 static 修饰的成员属于类。可以被类直接调用,也可以通过对象调用(建议通过类调用)。
  2. 静态代码块: (执行顺序:静态代码块—>非静态代码块—>构造方法)。 该类不管创建多少对象,静态代码块只执行一次.
  3. 静态内部类(static修饰类的话只能修饰内部类): 静态内部类与非静态内部类的区别: 1. 静态内部类的创建不需要依赖外部类对象的创建。2. 它不能使用任何外部类的非静态成员。
  4. 静态导包(用来导入类中的静态资源,1.5之后的新特性): import static ,可以直接使用类中静态成员变量和静态成员方法。

this:

this关键字用于引用类的当前实例。

class Manager {
    Employees[] employees;
     
    void manageEmployees() {
        int totalEmp = this.employees.length;
        System.out.println("Total employees: " + totalEmp);
        this.report();
    }
     
    void report() { }
}
  • this.employees.length:访问当前实例的变量。
  • this.report():访问当前实例的方法。

super:

super关键字用于从子类访问父类的变量和方法。

【问】深拷贝和浅拷贝?

Student类三个属性:name、age、teacher。

  • 浅拷贝一个对象时创建一个新对象,并对对象内的非静态属性和方法进行复制。对象的属性分为基本数据类型和引用类型。对基本数据类型的属性,直接在栈区进行复制;对引用类型的属性,则只复制引用但不复制对象,共同引用同一个对象。

  • 深拷贝一个对象时创建一个新对象,并对对象内的非静态属性和方法进行复制。对基本数据类型的属性,直接在栈区进行复制;对引用类型的属性,复制引用也复制对象,分别引用不同的对象。

 

【JAVA集合】

【问】java集合总结?哪些是并发集合(做了线程安全处理的集合)?

(1)

(2)

【List】

Vector:

读、写都做了同步。

CopyOnWriteArrayList:

写做了同步,读没做同步。适用于读多写少。(在写的时候会复制一个副本,对副本写,写完用副本替换原值。)

【Set】

CopyOnWriteArraySet:

基于CopyOnWriteArrayList,依然是CopyOnWrtite的特性,但不允许重复元素。

【Queue】

ConcurrentLinkedQueue:

通过无锁的方式实现,通常性能优于阻塞队列BlockingQueue。

LinkedBlockingQueue:

阻塞队列的一种实现类,典型应用场景是“生产者-消费者”模式中,如果生产快于消费,生产队列装满时会阻塞,等待消费。进行了读、写锁的分离。

【Deque】

LinkedBlockingDueue:

没有进行读、写锁的分离,因此同一时间只能有一个线程对其操作,因此在高并发应用中,它的性能要远远低于LinkedBlockingQueue,更低于ConcurrentLinkedQueue。

并发性能:ConcurrentLinkedQueue>LinkedBlockingQueue>LinkedBlockingDueue

【Map】

HashTable:

全部进行同步。

ConcurrentHashMap:

(jdk7)分段锁,锁粒度为segment。具体做法是将数组分为n段segment,用n个锁分别锁住这n个segment,并发性能是HashTable的n倍。通过ReenTrantLock加锁。无红黑树。

(jdk8)摒弃了 Segment 的概念,数据结构类似于java8的hashmap。锁的粒度就是HashEntry(首节点),只要不hash冲突,就不会产生并发。通过CAS+Synchronized加锁。有红黑树。

【问】ConcurrentHashMap详解?

JDK1.7:

put:

经过一次hash定位到Segment的位置,然后再hash定位到指定的HashEntry

get:

经过一次hash定位到Segment的位置,然后再hash定位到指定的HashEntry

size:

  1. 第一种方案他会使用不加锁的模式去尝试多次计算ConcurrentHashMap的size,最多三次,比较前后两次计算的结果,结果一致就认为当前没有元素加入,计算的结果是准确的
  2. 第二种方案是如果第一种方案不符合,他就会给每个Segment加上锁,然后计算ConcurrentHashMap的size返回

JDK1.8:

put:

没有hash冲突就直接调用Unsafe的方法CAS插入该元素。

get:

与 jdk1.8 hashmap一样

size:

使用一个volatile类型的变量baseCount记录元素的个数,当插入新数据或则删除数据时,会通过addCount()方法更新baseCount

【问】RandomAccess接口?

RandomAccess 接口 只是一个标识,没什么作用,只是说明该集合具 有快速随机访问功能。

【问】ArrayList的扩容机制?

扩容过程:

1.无参构造时,存储数组初始化容量为0;有参构造时,存储数组,初始化容量为传入参数。

2.第一次add时,若容量为0,发生扩容,扩为默认值10。

3.之后再调用add,且发现元素个数大于容量时,再次发生扩容:通过Arrays.copyOf()的方式将容量扩容为原来的1.5倍。

【问】HashMap和HashTable的区别?

 HashMapHashTable
线程安全性不安全安全
效率
键有无null允许有null,放在数组第0个位置不允许有null
红黑树机制jdk8以后有没有
扩容

初始默认16,扩容乘以二;

大小始终保证为2的幂次方

初始默认11,扩容乘以2n+1

 

 

 

 

 

 

【问】HashMap的底层实现?

(1)jdk1.7

数组(默认16)、链表+头插法(扩容产生死循环)

用HashEntry内部类实现的对象表示键值对。属性:K,V,next。

put实现:根据key的hashcode+扰动函数等一系列处理得到数组的索引位置。若发生哈希碰撞(两个key值不同,但算出来的数组索引相同),则在该索引位置通过头插法形成链表。

(2)jdk1.8的变化

做了改进:红黑树+尾插法

为什么红黑树?查询速度比链表快。

为什么尾插法?头插法的缺陷:并发条件下扩容rehash产生死循环(链表头插法的扩容会颠倒链表的顺序。在并发的时候,线程a的rehash使链表颠倒了引用顺序,线程b使链表保持原有的引用顺序,造成两个节点互相引用,最终形成了死循环)。

【问】HashMap链表升级为红黑树?红黑树退化为链表?

避免频繁的树化和退化过程:

(1)数组长度到64+链表长度到8;

(2)红黑树节点数量小于6,退化为链表;

【问】HashMap的加载因子?为什么是0.75?

(1)

加载因子是确定数组扩容时机的。扩容条件:存入数据的数量>=数组长度*加载因子。(反应内存利用率)

(2)

空间(内存)与时间(冲突)的平衡,官方测出来0.75最优。

【问】HashMap的数组长度为什么是2的幂次方?

为了减少哈希碰撞。计算索引时要对数组长度取余,用2的幂次方可以使结果的散列性更好。

【问】LinkedHashSet TreeSet 的区别?(均为有序Set)

  • LinkedHashSet:HashSet 的子类;能够按照添加的顺序遍历;

  • TreeSet:底层使用红黑树;能够按照添加元素的顺序进行遍历,排序的方式有自然排序和定制排序。(TreeMap也是红黑树)

  • 11
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值