看不习惯布局的,可点击查看本人微信公众号推文版—>微信推文<—
回答:
共同点:
都继承了Throwable类,在Java中,只有Throwable或其子类才能被捕获(catch)或者被抛出(throw)
不同点:
Error:在正常情况下,不太可能出现的问题。绝大部分Error都会导致程序本身(比如JVM)出现不可避免的,不可恢复的状态。所以这样的问题也没有在程序中进行处理的必要。
Exception:程序正常运行中,可以预料的意外情况。这部分问题被称为异常,大部分是程序员在程序中能够解决的。在异常下面还分为检查异常和运行时异常。
回答:
final:
可以修饰变量,方法,类。修饰类的时候,表示该类不允许被继承;修饰方法的时候;表示该方法不允许被overload;修饰变量的时候,表示该变量是不可变的(很重要),在进行多线程的时候,在进行函数式编程的时候,前者希望能让变量成为不可变的,后者会在编译期强制让变量声明为final的。finally:
这是Java中的一个语法糖,表明了一段无论如何都希望执行的代码,(会在return之前执行)除了System.exit(0),或者死循环出现的话,finally中的代码也确实会保证它的执行;finalize:
这是Object中的一个方法,它的作用是,调用之后希望能够提醒垃圾收集器回收垃圾。不过实际上,这个方法的效果是很差的,很可能带来反效果。
1、强引用:
特点:我们平常编码new出来的对象都是强引用,当JVM内存空间不足时,宁愿抛出OutOfMemoryError,使程序异常终止,也不会随意回收还存活的强引用对象。
2、软引用:特点:软引用通过SoftReference类实现,其生命周期比强引用短一些。只有当JVM内存空间不足时,才会试图回收软引用指向的对象:即JVM会确保在抛出OOM之前,清理软引用指向的对象。软引用可以和一个引用队列联合使用,如果软引用所引用的对象被垃圾回收器回收,JVM会将这个软引用加入到关联的引用队列中。后续我们可以调用ReferenceQueue的poll方法来检查是否它关心的对象被回收。如果队列为空,返回null,否则返回队列中最前面的Reference对象。应用场景:软引用通常用来实现内存敏感的缓存。如果还有空闲空间,可以暂时先保留缓存,当内存不足时清理掉。
3、弱引用:特点:弱引用通过WeakReference类实现,其生命周期比软引用还短。在垃圾回收器线程扫描它所管辖的内存区域时,一旦发现有弱引用的对象,就会回收它的内存。由于垃圾回收器线程是一个优先级很低的线程,因此不一定会很快回收弱引用对象。弱引用可以和一个引用队列联合使用,如果弱引用所引用的对象被垃圾回收器回收,JVM会将这个软引用加入到关联的引用队列中。
应用场景:弱引用同样可以用于内存敏感的缓存。4、幻象引用:
特点:幻象引用通过PhantomReference类来实现。无法通过幻象引用访问对象的任何属性或方法。幻象引用仅仅是提供了一种确保对象被finalize以后,做某些事情的机制。如果一个对象仅持有幻象引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。幻象引用必须和引用队列联合使用,当垃圾回收器准备回收一个对象时,如果发现它还有幻象引用,就会在回收对象的内存之前,把这个幻象引用加入到关联的引用队列中。
ReferenceQueue rq=new ReferenceQueue(); PhantomReference pr=new
PhantomReference(object, queue);
程序可以通过判断引用队列中是否已经加入了幻象引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个幻象引用已经加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取一些程序行动。
应用场景:可以用来跟踪对象被垃圾回收器回收的活动,当一个幻象引用关联的对象被垃圾收集器回收之前会收到一条系统通知。
回答:
String:
String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间。
String a = “a”; //假设a指向地址0x0001 a =
“b”;//重新赋值后a指向地址0x0002,但0x0001地址中保存的"a"依旧存在,但已经不再是a所指向的,a 已经指向了其它地址。
因此String的操作都是改变赋值地址而不是改变值操作。StringBuffer:
StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。
每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量。StringBuilder:
StringBuffer和StringBuilder类功能基本相似,主要区别在于StringBuffer类的方法是多线程、安全的,而StringBuilder不是线程安全的,相比而言,StringBuilder类会略微快一点。对于经常要改变值的字符串应该使用StringBuffer和StringBuilder类
回答:
说起动态代理,得说说了解一下代理模式。
什么是代理模式?代理模式是指通过代理静默地解决一些业务无关的问题,比如远程、安全、事务、日志、资源关闭……让应用开发者可以只关心他的业务。
四种代理模式:动态代理,静态代理,CGLib动态代理,JDK动态代理
静态代理:事先写好代理类,可以手工编写,也可以用工具生成。缺点是每个业务类都要对应一个代理类,非常不灵活。
动态代理:运行时自动生成代理对象。缺点是生成代理代理对象和调用代理方法都要额外花费时间。
JDK动态代理:基于Java反射机制实现,必须要实现了接口的业务类才能用这种办法生成代理对象。新版本也开始结合ASM机制。
cglib动态代理:基于ASM机制实现,通过生成业务类的子类作为代理类。 组成要素: 动态代理模式主要涉及三个要素:
1:抽象类接口
2:被代理类(具体实现抽象接口的类)
3:动态代理类:实际调用被代理类的方法和属性的类
实现方法:
实现动态代理的方法有很多,比如JDK自身提供的动态代理,就是主要利用了反射机制,还有其他的实现方式,比如利用字节码操作机制,类似ASM,CGLIB(基于ASM),Javassist等.
回答:
1、Integer是int的包装类,int则是java的一种基本数据类型2、Integer变量必须实例化后才能使用,而int变量不需要
3、Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
4、Integer的默认值是null,int的默认值是0
回答:
Hashtable、HashMap、TreeMap都是最常见的一些Map实现,是以键值对的形式存储和操作数据的容器类型。
Hashtable是早期Java类库提供的一个哈希表实现。 是同步的,不支持null键和null值。
由于同步导致的性能开销,所以不推荐使用。 HashMap是应用更为广泛的哈希表实现,行为大致与Hashtable一致。
主要区别在于HashMap不是同步的,支持null键和null值。
通常情况下HashMap进行put或get操作,可以达到常数时间的性能,所以他是绝大部分利用键值对存取场景的首选。
TreeMap则是基于红黑树的一种提供顺序访问Map。
和HashMap不同,他的put、get、remove之类的操作都是O(log(n))的时间复杂度。
具体顺序可以由指定的Comparator来决定,或者根据键的自然顺序来排序。
回答:
相同: 这三者都是实现集合框架中的List,也就是所谓的有序集合,因此具体功能也比较近似,比如都提供按照位置进行定位、添加或者删除的操作,都提供迭代器以遍历其内容等。但因为具体的设计区别,在行为、性能、线程安全等方面,表现又有很大不同。不同: Vector是Java早期提供的线程安全的动态数组,如果不需要线程安全,并不建议选择,毕竟同步是有额外开销的。Vector内部是使用对象数组来保存数据,可以根据需要自动的增加容量,当数组已满时,会创建新的数组,并拷贝原有数组数据。
ArrayList是应用更加广泛的动态数组实现,它本身不是线程安全的,所以性能要好很多。与Vector近似,ArrayList也是可以根据需要调整容量,不过两者的调整逻辑有所区别,Vector在扩容时会提高1倍,而ArrayList则是增加50%。
LinkedList顾名思义是Java提供的双向链表,所以它不需要像上面两种那样调整容量,它也不是线程安全的。
回答:
Java提供了不同层面的线程安全支持。在传统集合框架内部,除了Hashtable等同步容器,还提供了所谓的同步包装器。我们可以调用
Collections 工具类提供的包装方法,来获取一个同步的包装容器(如
Collections.synchronizedMap),但是它们都是利用非常粗粒度的同步方式,在高并发情况下,性能比较低下。
我们更加普遍的选择是利用并发包java.util.concurrent提供的线程安全容器类,它提供了: 各种并发容器,比如ConcurrentHashMap、CopyOnWriteArrayList。 各种线程安全队列(Queue/Deque),如ArrayBlockingQueue、SynchronousQueue。 各种有序容器的线程安全版本等。ConcurrentHashMap如何高效地保证?
首先,HashTable本身比较低效,因为它的实现方式基本上就是将put、get等方法加上“synchronized”简单来说,这就导致了所有并发操作都要竞争同一把锁,一个线程在进行同步操作时,其他线程只能等待,大大降低了并发操作的效率。
而ConcurrentHashMap的锁分段技术,就是将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一段数据的时候,其他段的数据也能被其他线程访问。
回答:
1.
Java中有很多IO方式,常见的分类就是 ①.传统阻塞IO–BIO(blocking IO), ②.非阻塞IO–NIO(Non-Blocking IO) , ③.异步非阻塞IO–A IO(Asynchronous
Non-blocking IO)。
2.
在 Java 1.4 中引入了 NIO 框架(java.nio 包),提供了 Channel、Selector、Buffer 等新的抽象,可以构建多路复用的、同步非阻塞 IO 程序,同时提供了更接近操作系统底层的高性能数据操作方式。在 Java 7 中,NIO 有了进一步的改进,也就是 NIO 2,引入了异步非阻塞 IO 方式,也有很多人叫它AIO(Asynchronous IO)。 异步 IO 操作基于事件和回调机制,可以简单理解为,应用操作直接返回,而不会阻塞在那里,当后台处理完成,操作系统会通知相应线程进行后续工作。
回答:
Java有多种比较典型的文件拷贝实现方法。
方法1:利用java.io类库。直接为源文件创建一个FileInputStream负责读取,然后再为目标文件创建一个FileOutputStream负责写入
方法2:利用java.nio类库提供的transferTo或transferFrom方法实现:方法3:直接调用java.nio.file.Files.copy()的实现。
关于拷贝效率的问题,其实与操作系统和配置等有关,总体上来说,NIO
transferTo/transferFrom的方式可能更快,因为它更能利用现代操作系统底层机制,避免不必要拷贝和上下文切换。
回答:
接口是对行为的抽象,它是抽象方法的集合,利用接口可以达到 API 定义和实现分离的目的。
接口,不能实例化;不能包含任何非常量成员,任何 field 都是隐含着 public static final的意义;同时,没有非静态方法实现,也就是说要么是抽象方法,要么是静态方法。Java 标准类库中,定义了非常多的接口,比如java.util.List。 抽象类是不能实例化的类,用 abstract 关键字修饰class,其目的主要是代码重用。除了不能实例化,形式上和一般的 Java类并没有太大区别,可以有一个或者多个抽象方法,也可以没有抽象方法。抽象类大多用于抽取相关 Java类的共用方法实现或者是共同成员变量,然后通过继承的方式达到代码复用的目的。
回答:
设计模式是人们为软件开发中相同表征的问题,抽象出的可重复利用的解决方案。在某种程度上,设计模式已经代表了一些特定情况的最佳实践。
按照模式的应用目标分类,设计模式可以分为创建型模式、结构型模式和行为型模式。
创建型模式,是对对象创建过程的各种问题和解决方案的总结,包括工厂模式(Factory、AbstractFactory),单例模式(Singleton)、构建器模式(Builder)、原型模式(Prototype)
结构型模式,是针对软件设计结构的总结,关注于类、对象继承、组合方式的实践经验。常见的结构型模式,包括桥接模式(Bridge)、适配器模式(Adapter)、装饰者模式(Decorator)、代理模式(Proxy)、组合模式(Composite)、外观模式(Facade)、享元模式(Flyweight)等。
行为型模式,是从类或对象之间交互、职责划分等角度总结的模式。策略模式(Strategy)、解释器模式(Interpreter)、命令模式(Command)、观察者模式(Observer)、迭代器模式(Iterator)、模板方法模式(Template
Method)、访问者模式(Visitor)