Java基础知识【浅浅总结十五条】

本文总结了Java编程中的十五个关键知识点,包括数据类型、String的不可继承性、StringBuffer与StringBuilder的区别、ArrayList与LinkedList的性能对比、类的实例化顺序、Map的实现类特点、ConcurrentHashMap的线程安全策略及其优化,以及反射、动态代理等核心概念。深入理解这些知识点对于提升Java编程技能至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 1、JAVA中的几种基本数据类型是什么,各自占用多少字节。

2、String类能被继承吗,为什么

不能。在Java中,只要是被定义为final的类,也可以说是被final修饰的类,就是不能被继承的。

3、String,Stringbuffer,StringBuilder的区别。

4、ArrayList和LinkedList有什么区别。

简单的区别:

  • 1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 (LinkedList是双向链表,有next也有previous)
  • 2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
  • 3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

深度的区别:

  1. 1.对ArrayList和LinkedList而言,在列表末尾增加一个元素所花的开销都是固定的。对ArrayList而言,主要是在内部数组中增加一项,指向所添加的元素,偶尔可能会导致对数组重新进行分配;而对LinkedList而言,这个开销是统一的,分配一个内部Entry对象。
  2. 2.在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入或删除一个元素的开销是固定的。
  3. 3.LinkedList不支持高效的随机元素访问。
  4. 4.ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间

5、讲讲类的实例化顺序。

问题:比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字 段,当new的时候,他们的执行顺序。

答案: 类加载器实例化时进行的操作步骤(加载–>连接->初始化)。 父类静态变量、 父类静态代码块、 子类静态变量、 子类静态代码块、 父类非静态变量(父类实例成员变量)、 父类构造函数、 子类非静态变量(子类实例成员变量)、 子类构造函数。

6、用过哪些Map类,都有什么区别。

问题:比如HashMap是线程安全的吗,并发下使用的Map是什么,他们 内部原理分别是什么,比如存储方式,hashcode,扩容,默认容量等。 答案: 不安全,并发下使用ConcurrentHashMap。

7、JAVA8的ConcurrentHashMap为什么放弃了分段锁?

原因:通过 JDK 的源码和官方文档看来, 他们认为的弃用分段锁的原因由以下几点: 1、加入多个分段锁浪费内存空间。 2、生产环境中, map 在放入时竞争同一个锁的概率非常小,分段锁反而会造成更新等操作的长时间等待。 3、为了提高 GC 的效率

既然弃用了分段锁, 那么一定由新的线程安全方案, 我们来看看源码是怎么解决线程安全的呢?CAS

首先通过 hash 找到对应链表过后, 查看是否是第一个object, 如果是, 直接用cas原则插入,无需加锁,然后如果不是链表第一个object, 则直接用链表第一个object加锁,这里加的锁是synchronized,虽然效率不如 ReentrantLock, 但节约了空间,这里会一直用第一个object为锁, 直到重新计算map大小, 比如扩容或者操作了第一个object为止。

8、ConcurrentHashMap(JDK1.8)为什么要使用synchronized而不是如ReentranLock这样的可重入锁?

可以从下面几个方面讲述: 锁的粒度 首先锁的粒度并没有变粗,甚至变得更细了。每当扩容一次,ConcurrentHashMap的并发度就扩大一倍。 Hash冲突 JDK1.7中,ConcurrentHashMap从过二次hash的方式(Segment -> HashEntry)能够快速的找到查找的元素。在1.8中通过链表加红黑树的形式弥补了put、get时的性能差距。 扩容 JDK1.8中,在ConcurrentHashmap进行扩容时,其他线程可以通过检测数组中的节点决定是否对这条链表(红黑树)进行扩容,减小了扩容的粒度,提高了扩容的效率。

为什么是synchronized,而不是可重入锁

  1. 减少内存开销 假设使用可重入锁来获得同步支持,那么每个节点都需要通过继承AQS来获得同步支持。但并不是每个节点都需要获得同步支持的,只有链表的头节点(红黑树的根节点)需要同步,这无疑带来了巨大内存浪费。
  2. 获得JVM的支持 可重入锁毕竟是API这个级别的,后续的性能优化空间很小。 synchronized则是JVM直接支持的,JVM能够在运行时作出相应的优化措施:锁粗化、锁消除、锁自旋等等。这就使得synchronized能够随着JDK版本的升级而不改动代码的前提下获得性能上的提升。

9、有没有有顺序的Map实现类,如果有,他们是怎么保证有序的。

Hashmap和Hashtable 都不是有序的。 TreeMap和LinkedHashmap都是有序的。(TreeMap默认是key升序,LinkedHashmap默认是数据插入顺序) TreeMap是基于比较器Comparator来实现有序的。 LinkedHashmap是基于链表来实现数据插入有序的。

10、抽象类和接口的区别,类可以继承多个类么,接口可以继承多个接口么,类可以实现多个接口 么。

区别:

  • 1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象
  •  2、抽象类要被子类继承,接口要被类实现。
  • 3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现
  • 4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
  • 5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。
  • 6、抽象方法只能申明,不能实现。abstract void abc();不能写成abstract void abc(){}。
  • 7、抽象类里可以没有抽象方法
  • 8、如果一个类里有抽象方法,那么这个类只能是抽象类
  • 9、抽象方法要被实现,所以不能是静态的,也不能是私有的。
  • 10、接口可继承接口,并可多继承接口,但类只能单根继承。
  • 类不能继承多个类 接口可以继承多个接口 类可以实现多个接口
  • 如果你现在正在学习java,我这有自己整理的一些开发工具,学习手册,PDF的课件资料,可以加入我的Java技术交流圈603835449获取,希望能帮助到孤军前行的你

11、继承和聚合的区别在哪。

继承 指的是一个类继承另外的一个类的功能,并可以增加它自己的新功能的能力,继承是类与类或者接口与接口之间最常见的关系;在Java中此类关系通过关键字extends明确标识。


聚合

聚合体现的是整体与部分、拥有的关系,此时整体与部分之间是可分离的,他们可以具有各自的生命周期;比如计算机与CPU、公司与员工的关系等;

12、IO模型有哪些,讲讲你理解的nio ,他和bio,aio的区别是啥,谈谈reactor模型。

各IO的区别:

reactor是什么?

  1. 事件驱动
  2. 可以处理一个或多个输入源
  3. 通过Service Handle同步的将输入事件采用多路复用分发给相应的Request Handler(一个或多个)处理

13、反射的原理,反射创建类实例的三种方式是什么。

//创建Class对象的方式一:(对象.getClass()),获取类中的字节码文件
Class class1 = p1.getClass();

//创建Class对象的方式二:(类.class:需要输入一个明确的类,任意一个类型都有一个静态的class属性)
Class class3 = Person.class;

//创建Class对象的方式三:(forName():传入时只需要以字符串的方式传入即可)
//通过Class类的一个forName(String className)静态方法返回一个Class对象,className必须是全路径名称;
//Class.forName()有异常:ClassNotFoundException
Class   class4 = Class.forName("cn.xbmchina.Person");
        

14、反射中,Class.forName和ClassLoader区别 。

Class.forName(className)方法,内部实际调用的方法是 Class.forName(className,true,classloader); 第2个boolean参数表示类是否需要初始化, Class.forName(className)默认是需要初始化。 一旦初始化,就会触发目标对象的 static块代码执行,static参数也也会被再次初始化。 ClassLoader.loadClass(className)方法,内部实际调用的方法是 ClassLoader.loadClass(className,false); 第2个 boolean参数,表示目标对象是否进行链接,false表示不进行链接,由上面介绍可以, 不进行链接意味着不进行包括初始化等一些列步骤,那么静态块和静态对象就不会得到执行

15、描述动态代理的几种实现方式,分别说出相应的优缺点。

原理区别:

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP  2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP

3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

如何强制使用CGLIB实现AOP?  (1)添加CGLIB库,SPRING_HOME/cglib/*.jar  (2)在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

JDK动态代理和CGLIB字节码生成的区别?  (1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类  (2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法    因为是继承,所以该类或方法最好不要声明成final


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值