java string 过长_Java一些基础问题

exception和error的区别?

实际上你使用Idea看uml图的时候,你会发现exception和error都是继承ThrowAble类。

一个exception是程序正在运行,可以预料的一个意外情况(注意是程序正常运行),异常可分为可检查异常和不可检查一场,不可检查异常就是我们常见的空指针异常。可检查的异常就是我们业务代码常用的检查异常。

而error是程序正常情况下不大会出现的一些情况,这些情况可能使程序处于不正常的情况,内存溢出这些

扩展:其实try catch会造成额外的损耗,所以看情况,但是不该省的地方一定不能省。

第二点RPC,第二方包要注意throwable来拦截,因为很可能是异常或者错误,直接用他们的父类。(这里阿里的Java规范提到过)

6ba8893af9ed28ebda9f368da7dac9f3.png

final ,finally,finalize的区别?

首先这结果f字头的保留词或者是关键词,还是有很大不同的。

final常见的关键词,修饰的是不可重写的(经常与静态关键词static一起使用,static是提前加载,final是不能改变,两个经常和在一起使用),final可以修饰常量,方法,final修饰的类是不可以继承扩展的,通常是为了保证平台的安全性。

finally是Java的一种机制,也就是一种一定执行的机制。经常搭配try-finally或者try-catch-finally来使用,保证JDBC链接,保证ulock等。

finalize是一种基础方法,是一种保证垃圾回收的方法,不推荐使用。

扩展:final作为这里面最常见的关键字,就是不使用,在看源码第三方包都会看到,看着跟这种修饰的类或者方法,明确表示出不想使用者进行改变。final修饰的变量常量,由于是不可变的,这样多线程开发的时候不用考虑,防御性拷贝,就是我先复制一个省着你以后变了我跟不上。

finally作为一个机制,保证被执行,有的时候会以代码的形式来考察,比如:

        try {
            System.out.println("zp  很帅而且很瘦");
        }finally {
            System.out.println("ZP  很帅但是有亿点点胖");
             }

        try {
            System.out.println("zp  人很不错而且很瘦");
            System.exit(1);
        }finally {
            System.out.println("ZP  人很不错但是有亿点点胖");
        }

输出结果是啥,注意第二个部分多了个exit方法,exit(1)异常退出

284cb2554b4c348b27d23b83d766e3d4.png

finalize那么不堪吗?新的JDK都已经表起来了,因为他可能会拖慢垃圾回收进程,finalize使被操作的对象成为“特殊的”,JVM会对他进行额外照顾,也就是回收周期内也不会管他。

强引用,软引用,弱引用和幻想引用的区别?具体使用场景?

强引用就是我们常见的,指向一个对象,表明这个对象还活着就不会对他进行垃圾回收,但是如果超过了作用域或者值为null还是会被收集的。

例子:

    Object strongReference = new Object();

软引用,对强引用的弱化的引用,也就是内存不够了,GC就会收集这些,例子(注意软引用的定义)

    // 强引用
    String strongReference = new String("abc");
    // 软引用
    String str = new String("abc");
    SoftReference<String> softReference = new SoftReference<String>(str);

弱引用,这种引用不仅不能像强引用这些,可以避免对象被垃圾回收。他只是提供了一种映射关系,对象存在就会调用,没有就实例化。和弱引用对比就是,弱引用最起码还能有个周期,就是内存不够才会被回收,但是软引用GC的时候直接就被回收(好在垃圾回收优先度低,所以弱引用还能挣扎一会)

幻想引用也叫做虚引用,实际上虽然名字里有引用两个字,但是不能指向对象,只是方便通过它监控回收对象的监控(finalize对应改进Cleaner,实际通过幻想引用来监控是否销毁)

使用场景:强引用经常用,软引用和弱引用缓存设计,内存敏感的中间件会涉及到,幻想引用虚引用对应的是Cleaner类。

String,StringBuilder,StringBuffer有什么区别?

这个是真的会问的频率超级高,包括大厂的面试。

String是个final class,不能被修改也就是从原生就保证不可更改性,也就是说线程安全的

StringBuffer和StringBuilder其实两者都是AbstractStringBuilder的子类,实际他们中很多方法是相同的,只不过StringBuffer里面对应的方法是synchrpized修饰的,所以是线程安全的。

那么StringBuilder这个的意义何在呢?又不是线程安全的,因为他够快啊,StringBuilder有一个char数组,但是String相加的时候会创建对象,对比起来肯定是操作数组要比创建对象要更快。

延伸:为什么String 相加用+号不能完全代替StringBuilder和StringBuffer?

首先知道StringBuilder和StringtBuffer是一个父类,“一奶同胞”,但是由于StringBuffer线程安全导致性能消耗,但是对字符串的操作原理是一样的。

String是immutable的不断创建新的对象,非常影响性能。

三者比较效率,如果次数够多的话,String都打不过StringBuffer,但是操作次数少的话实际上可读性上可以选择String +的。

Java反射机制,动态代理基于什么原理?

实际上要注意反射机制是Java的一个基础功能,动态代理是一个机制,是一种动态建立代理动态处理机制。动态代理可以通过发射机制来实现,但是不一定一定由反射机制实现,比如字节码等也可以实现动态代理。同样反射也不是只可以实现动态代理,RPC调用,AOP都会用到反射机制。

延伸:就是动态代理看名字就知道利用了代理模式,但是很多动态代理利用了装饰器模式。

int和Integer的区别,integer的缓存范围?

int是Java的基础类型,不是类。

Integer是int的包装类,提供了许多基本操作在里面,如数字运算和字符串转换。

Integer缓存范围就是-127到128(应该是-8到8吧)

对比Vector,ArrayList,LinkedList有何区别?

实际上Vector是一个线程安全的动态数组。(效率低使用频率不高)

ArrayList是一个高效的动态数组但是线程不安全。

LinkedList是双向列表,但是也是线程不安全的

延伸:

实际上集合是Java的一个很重要的部分,基础类型有时候不够方便,也没有一些数据结构带来的特性。

下面是一些图来理解Java的集合,要和在一起看,因为这几个都不是完全,比如第一个collection少了个set一起看这些图,这些图都是网路上比较火引用比较多的图。

set是一个不重复的集合,像set是由map进一步完成的,HashSet是由HashMap的基础上添加一些对应数据结构的处理来完成的。

Java的集合常用的很多是线程不安全的,但实际上collection有一个concurrent的包,里面都是线程安全的,除此之外我们工作中为了效率会使用google的集合工具包。

069dfce79e069b021a8b128b12b3daef.png

62406de1cd05c468a21bc85aa7f87499.png

9b307af3367914ea5f26e919b17a7473.png

对比HashMap,HashTable,TreeMap有什么不同?

实际上这三者都是Map的一个实现,也就是键值对形式的存储

HashTable是线程安全的,是一个哈希表的实现不支持null值,效率低不推荐。

HashMap是哈希表更广泛的实现,但是线程不安全的,所以多线程并发不推荐

TreeMap是对应红黑树的实现

延伸:

这也是经常考,考到烂的一个问题

Map的结构

474f3d7e21013bac20582dc059ab3d0b.png

HashMap源码分析

注意两者:1 容量和负载系数(有的材料叫做负载因子) 2树化

结构实现上实际可以看为数组和链表的结合,根据哈希值对应每一个桶的值,键值对寻址,然后对应的是一个链表,如果链表的长度超过了阀值,就会链表进行树化,链表变成树,这个阀值一般是8.

e019582c1ce513e6664d62ae9542e784.png

负载因子一般默认是8,会有人问设的大或者设的小有什么问题?

存储元素 》负载因子*容量,扩容,负载因子设的大影响效率,设的小频繁扩容空间浪费

为什么要树化?

因为哈希碰撞导致的,如果链表过长会导致效率不高,树化会帮助提高效率

解决哈希冲突还有哪些方法?

再哈希,开放定址等

hashMap源码两主要地方放负载因子和树化

如何保证集合是线程安全的,ConCurrentHashMap高效的原理?

Java集合有同步包装容器但是锁的粒度比较粗,影响效率。

所以Java也提供了许多效率高并且线程安全的集合工具。

ConCurrentHashMap主要用到了分离锁来提高效率。

延伸:

ConCurrentHashMap的线程安全和高效一是使用分离锁,就是内部分段是HashEntry数组。第二是这些数组用volatile来修饰的。

分离锁就是Concurrent里面细化的锁,每个桶有一个自己的锁,叫做分离锁。(分离对应HashMap的数据结构)

8a02c7d2ba768e16a8fe641d141ccbd6.png

Java提供了哪些IO方式,NIO如何多路复用?

JavadeIO方式有差不多三种

传统IO,同步阻塞式的,http://java.net里面的一些API有时候也算作IO

NIO,多路复用,非阻塞式IO,通过Chanel,Selector,Buffer来操作,实现的原理操作系统高性能数据操作方式。

NIO2也叫AIO,异步非阻塞,就是完成了操作系统返回,没完成也不会阻塞在哪里,完成后操作系统会提醒后续操作。

扩展:同步和异步

Java几种拷贝方式?哪一种以高效?

首先Java的IO流有对应的拷贝操作

然后Java的NIO也有类似的拷贝操作,transfromTo,transfromFrom的操作

还有就是File类的copy操作。

要说那个最高效肯定是NIO的拷贝操作,因为减少了用户态内核态的切换,减少了IO操作。

延伸:首先要知道为什NIO会比IO效率高的前提,是你要知道有一个内核态和用户态的区别,实际上操作系统内核,和驱动都在内核态运行,内核态相对操作的权限比较高。

IO拷贝操作实例图

974a959a0096e27f7d65bc1657a65fcf.png

NIO的拷贝就少了用户态向内核态的切换,以transferTo为例

1780ca038552188c05a9e76dc786eea8.png

接口和抽象类的区别?

实际上接口和抽象类都是Java的基础机制

接口是对行为的抽象,他是抽象方法的集合。利用接口可以达到API定义和API的实现进行分离的目的。接口不能实例化,而且里面的不能包含任何成员变量,任何field都包含public static final ,没有非静态方法的实现,要不然是静态方法要不然是抽象方法。

抽象类也是不能实例化的类,多了个Abstract来修饰类,可以有一个多个抽象方法,也可以没有。抽象类做的功能更多是抽取,抽取Java类共用的方法或者共同的成员变量。通过继承的方式达到方法的复用的方式。Java的集合包里面有很多对应的,比如可以看上面我那个关于集合的图,AbstractMap父类,继承EnumMap,HashMap,TreeMap

扩展:

JAVA8以后接口里面也可以实现方法,默认方法实现default method

接口和抽象类,一个是行为的抽象,API常用到,一个是框架弄出来的抽取共有的方法或者变量。

除此之外注解和他们也有点像,而且注解还能添加参数。

谈谈你知道的设计模式?请手动实现单例模式,spring等框架都用了那些设计模式?

其实设计模式可以划分为三大类:创新型模式,结构型模式,行为型模式

创新型:对对象创建的各种总结,以及各种问题的解决方案。比如工厂模式,构造器模式,单例模式,原型模式

构造型:对于软件设计结构的总结,类,对象的继承,组合的实现总结。包括桥接模式,适配器模式,装饰着模式,代理模式,组合模式,外观模式,享元模式

行为型:类对象,行为指责划分的总结,策略模式,解释器模式,命令模式,观察者模式,迭代器模式,模版方法模式,访问者模式

Spring中里面默认是单例,bean的生成是采用工厂模式,各种各样的监听器采用的是观察者模式,还有一些jdbcTemplete应用了模版模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值