JAVA基础阶段总结

JAVA基础阶段总结

重载(Overload)和重写(Override)的区别是什么?

  • 重载是某个方法,可以有不同的参数列表、返回值和修饰符。
  • 重写是子类继承父类时,子类想对父类的方法做出修改,就可以@Override注释,写出跟父类相同的方法体(返回值的范围可以比父类小),方法内容随意重写。

java8的新特性你都了解哪些?

lamda表达式、方法引用表达式、Stream流、新的时间类等待
在项目中常用的lamada表达式和方法引用表达式,比如对分块文件列表进行按 名称排序,就是用了表达式和comparingInt方法来实现的

抽象类和接口的区别?

  1. 抽象类一般用作实体类的抽象,用abstract修饰,接口一般是在service层、dao层之类的系统架构上面使用,是对动作的抽象,用interface修饰。
  2. 一个抽象类只能被单继承(extends),一个接口可以被多实现(implements)。
  3. 实现一个接口,必须实现接口中的所有方法,抽象类可以有选择地进行继承。

==和equals()的区别是什么?

  • ==是判断两个变量或实例是不是指向同一个内存空间。equals是判断两个变量或实例所指向的内存空间的值是不是相同。
  • ==是一个操作符,equals是一个方法。
  • 常用的Object 的 equals() 方法其实就是 ==;而String 的 equals()重写了此方法,比较对象的值。
    所以equals() 方法有没有被重写是判断其与 == 的区别的主要关注点。

阐述final、finally、finalize 的区别

final

  • final 是一个修饰符,意为最终态。如果一个类被声明为final,意味着它不能再派生新的子类。
  • 修饰类,类不能被继承
  • 修饰变量,变量是常量
  • 修饰方法,方法不能被重写
    finally
    finally是异常处理的一部分,用于释放资源,一般来说finally里面的代码肯定会执行
    finalize
  • finalize()是Object中的方法,用于垃圾回收。当一个对象被虚拟机宣告死亡时会先调用finalize()方法,让此对象处理它生前最后的事情。

String类的常用方法都有哪些?

length()返回字符串的长度 , equals()比较字符串, getByte()返回字符串的byte类数组, trim()去除字符串两端空白, split()分割字符串,返回分割后的字符串数组,replace()字符串替换,toLowerCase()字符串转换小写,toUpperCase()字符串转换大写, substring()截取字符串 ,indexOf()返回指定字符串索引 ...

Break和Continue有什么区别?

用Break语句可以使流程跳出switch语句体,也可以用Break语句在循环结构中终止本层循环体,从而提前结束本层循环。
Continue是结束本次循环,继续下一次循环。

数据类型

String,StringBuffer,StringBuilder的区别是什么?

String是一个用final修饰的字符数组,是一个不可变的对象,每次修改字符串对象都等同于生成了一个新的对象,然后将指针指向新对象。
StringBuffer和StringBuilder是可变的字符序列,都在原来的对象本身进行操作;
StringBuffer是线程安全的;StringBuilder是线程不安全的,但是StringBuilder的速度更快一些。

int 与Interger 的区别?

首先最本质的区别就是 int是一个数据基本类型,而 Integer是一个基本类型的包装类。

  • int是直接存储数据值,而Integer 是对象的引用。(当new 一个Interger时,实际上是生成一个指针指向此对象)
  • Integer变量必须实例化后才能使用,而int变量不需要。
  • int默认值为0,Integer默认值为 null。

集合

平常用过哪些集合?

常用的就是 ArrayList, LinkedList, HashMap, 其他的还有 TreeMap,HashTable,TreeSet,HashSet等。

List,Set,Map的区别?

首先,List和Set都是Collection下的子接口,而Map是与Collection同级的接口。

  • Set接口最重要的一点是不包含重复元素,而且是无序的,它下面的TreeSet实现了有序。
  • List接口允许重复元素,并且是保证顺序的,可以插入 null元素,其下面常用的有LinkedList和ArrayList。
  • Map是通过键值对的方式存储数据,每一个键都可以获取唯一对应的值。

LinkedList 和 ArrayList 的区别?

ArrayList:

  • 底层数据结构是数组
  • 由于其存放数据的是一块连续的内存空间,就可以根据数组的首地址加上偏移量,直接计算出第n个元素的内存位置,所以它查询快。
  • 还是由于其数据结构的原因,当想要在中间插入一条数据时,后面的数据需要全部往后挪一位,甚至是要将新数组重新分配内存空间,增删慢。
    LinkedList:
  • 底层数据结构是双向链表
  • LinkedList存放数据是分散的,每个数据保存自身数据 + 下一个数据内存地址,查询时要从头部顺着链子依次查,所以它查询慢。
  • 增删快,LinkedList想要插入数据,只需要将插入位置断开,安插进去,修改的只是节点之间的引用。

ArrayList 为什么线程不安全?怎么解决?

ArrayList添加数据时,会分为两步:存放数据和修改size。当存放数据后线程被抢,然后另一个线程也存放数据,就会导致存放数据实际只有一条,而size为2。
解决方法:1. 使用synchronized关键字。2. 使用Collection类提供的synchronizedList()方法。

怎么删除list中的某个数据?

  1. 暴力for循环遍历,调用remove
  2. 原list叫 listA,将某个数据存为另一个 listB,listA调用removeAll方法,删除 listB
  3. 得到该 list 的迭代器,使用迭代器的remove方法。

java的队列有了解吗?

队列即 Queue,是与LIst,Set同一级别的接口。LinkedList实现了Queue接口下的子接口Deque(双端队列)。
没有实现阻塞接口的有: LinkedList, priorityQueue,ConcurrentLinkedQueue。
实现阻塞接口的:ArrayBlockingQueue(基于数组的有界队列),LinkedBlockingQueue(基于链接的有界队列),PriorityBlockingQueue(基于优先级的无界队列),DelayQueueSynchronousQueue

HashMap

HashMap底层结构是什么?

HashMap的底层结构是链表+红黑树。HashMap如果在创建时没有指定容量,默认初始容量为16,扩容阈值为数组长度的0.75.每次扩容翻倍。当HashMap长度小于8时使用链表,而当HashMap长度大于8时自动转化为红黑树。

HashMap是否是线程安全的?如何保证HashMap线程安全?

HashMap不是线程安全的。

  • 使用Collection类里面的synchronizedMap()包装一下,即可得到线程安全的map;(使用的是悲观锁)
  • 使用ConcurrentHashMap类,可以直接得到一个线程安全的HashMap(采用的是乐观锁)

HashMap为什么初始化大小为16?

HashMap的初始化大小是将初始化大小二进制按位与,而扩容机制是HashMap每次扩容都是以2的整数次幂进行扩容。因此最合适的初始化大小是16,4和8理论上也可以,但是因为太小容易导致map扩容影响性能,太浪费资源。

红黑树和链表怎么进行转化?

当HashMap长度小于8时使用链表,而当HashMap长度大于8时自动转化为红黑树。目的是为了减少搜索时间。
纯链表的平均查找长度为(n+1)/2,红黑树平均查找长度则为log2n。长度为8的时候,红黑树平均查找长度为3,链表平均查找长度为8/2=4,这才有转换为树的必要。链表长度如果小于等于6,6/2=3,速度已经很快,并且转化为树结构和生成树的时间不会很短,所以没必要转成红黑树。

HashMap和TreeMap的区别?

  1. 实现
    HashMap基于哈希表,
    TreeMap基于红黑树。
  2. 存储和遍历
    HashMap随机存,随机遍历
    TreeMap升序存,排序遍历
  3. 性能损耗
    HashMap基本无损耗
    TreeMap插入删除速度慢,需要维护树的平衡。
  4. 键值对
    HashMap键值均可为null;
    TreeMap键值均不可为null。
  5. 安全性和效率
    HashMap不安全,效率高;
    TreeMap不安全,效率低。

HashMap和HashTable有什么区别?

HashMap线程不安全,效率高,键值允许为null,非同步,适合单线程环境;
HashTable线程安全,效率低,不允许键值为null,同步,适合多线程。
但是多线程环境下仍然不建议使用HashTable,因为

  1. HashTable是遗留类,内部实现很多没有优化,冗余多。
  2. 内部全部加了syn锁,重量级锁,效率低。
  3. 多线程有了更好的同步的ConcurrentHashMap替代。

HashMap和LinkedHashMap有什么区别?

HashMap是最常用的一个map,根据key的hash值来存储数据,底层是链表+红黑树,当长度小于8时使用链表,大于8时自动转化为红黑树。HashMap是线程不安全的,如果需要线程安全,可以使用Collections.synchronizedMap()来获取一个线程安全的map,也可以直接使用ConcurrentHashMap类来获取一个线程安全的HashMap。
LinkedHashMap是HashMap下面的一个子类,跟HashMap的区别就是HashMap是无序的,而LInkedHashMap是可以保存插入顺序的。当对输出顺序有要求的话可以使用,一般而言LinkedHashMap的性能会比HashMap差一点(特殊情况:HashMap容量大而实际数据少时会比LinkedHashMap差,因为LinkedHashMap遍历速度只与实际数据有关,而HashMap与容量也有关)。

synchronized 和 volatile 的区别是什么?

  1. synchronized 可以作用于变量,方法,对象;volatile 只能作用于变量。
  2. synchronized 可以保证线程间的有序性,原子性和可见性;volatile只保证了可见性和有序性,无法保证原子性。
  3. synchronized 有可能导致线程阻塞,volatile 线程不阻塞。
  4. volatile标记的变量不会编译器优化,synchronized标记的变量可以被编译器优化。

线程

进程和线程的区别?

进程就等于是电脑里运行的程序,线程就等于是可以让一个进程同时执行多个任务,一个进程可以有多个线程。

java里面创建线程的方式

  1. 实现 Runnable 接口的 run() 方法,然后通过Thread的 start() 方法开启线程。
  2. 继承 Thread 类,重写 run() 方法,这个本质上与Runnable接口的方式一样,因为 Thread 类本身就实现了 Runnable 接口。
  3. 实现 Callable 接口的 call() 方法,然后通过 Future 的 get() 方法进行开启线程。与另外两个的区别是这个有返回值。
  4. 通过 JUC里面的线程池。

java中的线程池是什么,有哪些常用的参数?

线程池的基本功能就是进行线程的复用,当程序需要一个线程时,会先从线程池里面捞一下空闲线程来使用,用完后会将线程重新放入线程池。
corepoolSize:池中所保存的常驻线程数。
maxmumpoolSize:池中允许的最大线程数。
keepAliveTime:多余的空闲线程最多存活时间。
unit:keepAliveTime 的单位。
handler:拒绝策略,表示当队列满了,如何拒绝。java默认提供了4种饱和和策略的实现方式:终止,抛弃,抛弃最旧的,调用者运行。
workQueue:任务队列。
threadFactory:表示生成线程池中工作线程的线程工厂。

常用线程池?

  1. newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理器需要,可灵活回收空闲线程,若无可回收,则新建线程。
  2. newFixedThreadPool:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  3. newScheduledThreadpool:创建一个定长线程池,支持定时及周期性任务执行。
  4. newSingleThreadExecutor:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,LIFO)执行。

线程池创建方式?

  1. 使用ThreadPoolExecutor类
  2. 使用Executor类
    两种方式本质上是一种方式,都是通过ThreadPoolExecutor类的方式。

线程池的优点?

  1. 重用存在的线程。减少对象创建,消亡的开销,性能更好。
  2. 可有效的控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
  3. 提供定时执行,定期执行,单线程,并发数控制等功能。

  1. 降低资源消耗:重复利用线程,减少创建和销毁造成的消耗。
  2. 提升响应速度:任务到达,不需要创建,立即执行。
  3. 提高可管理性:线程是CPU调度和分派的基本单位

服务端同步和异步你是怎么理解的?

同步 在一定程度上可以看做是单线程,这个线程请求一个方法后就待这个方法给它回复,否则它不往下执行。
异步在一定程度上可以看做是多线程,请求一个方法后就不管了,继续执行其他方法。

同步,可以理解为在执行完一个函数或方法后,一直等待系统返回值或消息,这时程序是处于阻塞的,只有接收到返回的值或消息后才往下执行其他的命令。
异步,执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程,那么当系统接收到返回值或消息时,系统会自动触发委托的异步过程,从而完成一个完整的流程。

JVM

分别解释一下栈和堆

栈是运行时的单位,解决程序如何执行,代表处理逻辑。
堆是存储单位,解决数据存储问题,代表数据

JVM类加载机制,调优机制是什么?

  • JVM类加载机制
    jvm类加载机制分为五个部分:加载,验证,准备,解析,初始化。
    虚拟机将class文件加载到内存,并对数据校验,准备和解析,之后完成初始化。
    加载就是JVM将字节码转化为二进制字节流加载到内存中,然后为这个类在JVM方法区创建一个Class对象(访问入口);
    验证是连接阶段的第一步,这一步主要就是未来确保class文件符合虚拟机的要求;
    准备阶段是最重要的,这个阶段会为类变量分配内存并初始化。初始化时会为类变量赋予其数据类型的零值,而不是代码里初始化的值,例如
public static int number = 3 ;
public static final finalNumber = 3 ;

这里number初始化值是0,而不是3.
但是如果被final修饰,即成为了常量,那么在准备阶段就会被赋值为3,好比这里的finalNumber的值为3。
解析阶段会将常量池内的符号引用替换为直接引用。
1. 符号引用:简单的理解就是字符串,比如引用一个类,java.uitl.ArrayList 这就是一个符号引用,字符串引用的对象不一定被加载。
2. 直接引用:指针或者地址偏移量。引用对象一定在内存(已经加载)。
初始化阶段会执行类构造器的clinit()方法,为类变量赋予正确的初始值(之前在准备阶段只是分配空间并赋予0值,现在才赋予正确值),而初始值设定有两种方法:

  1. 直接声明类变量的指定初始值,比如上面的number=3,就是此时赋予;
  2. 使用静态代码块进行指定初始值。
  • 调优机制
    对jvm内存系统级的调优主要目的是减少GC的频率和full GC的次数,过多的GC和full GC会占用很多的系统资源(主要是CPU),影响系统的吞吐量。
  1. 老年代空间不足:(会引起Full GC)
    • 尽量让对象在年轻代GC时被回收;
    • 让对象在年轻代多存活一段时间;
    • 不要创建过大的对象;
    • 数组避免直接在老年代创建对象。
  2. 年轻代空间不足:
    • 增大年轻代空间,避免太多静态对象;
    • 控制好年轻代和老年代的比例;
  3. 垃圾回收尽量不要手动触发 ,尽量依靠JVM自身的机制。

调优手段主要是通过控制堆内存的各个部分的比例和GC策略

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏路加

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值