什么是面向对象?
面向过程是分析出实现需求所需要的步骤,通过函数一步一步实现这些步骤,然后依次调用。将实现步骤化。
面向对象是把整个需求按照特点、功能划分,将这些存在共性的部分封装成对象。创建对象不是为了完成某一个步骤,而是描述某个事物在解决问题中的行文。将实现行为化。
面向对象的特征
- 封装:隐藏对象内部的特性和行为。
- 继承:子类继承父类的特性和行为。
- 多态:不同类的对象,对同一消息,做出不同响应。
- 抽象:把一类事物共有的属性和行为提出来,形成一个模板。
重载和重写的区别
- 重写 override
- 方法名、参数、返回值相同
- 方法被定义为final 不能被重写
- 存在于父类和子类之间
- 重载 overload
- 参数类型、个数、顺序至少有一个不同
- 不能重载只有返回值不同的方法名
- 存在于父类和子类、同类中
什么是字节码
衍生问题,Java 是编译执行的语言,还是解释执行的语言。
- 编译型语言:在被执行之前需要一个专门的编译过程,把程序编译为机器语言的文件,比如windows下的exe文件。下次不需要再编译,可以直接在机器上运行。效率比较高。编译型语言有C、C++等。
- 解释型语言:不需要编译。在运行时翻译成机器识别的机器语言。每次执行都需要一次翻译的过程。效率比较低。解释型语言有C#、Python等。
Java中引入虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器。这台虚拟的机器在任何平台上都提供给编译程序一个共同的接口。
编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机转化为特定系统的机器码执行。在Java中这种虚拟机理解的代码叫做字节码(即扩展名为.class的文件),它不面向任何的处理器,只面向虚拟机。
每一种平台的解释器是不同的。但是实现的虚拟机是相同的。Java源程序经过编译器编译后编程字节码,字节码由虚拟机解释器执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机器上的机器码,然后在特定的机器上运行。这也就解释了Java的编译与解释并存的特点。
什么是自动拆装箱
自动装箱和拆箱,就是基本类型和引用类型之间的转换。
- 为了让代码简练,Java5 引入了具有在原始类型和对象类型自动转换的装箱和拆箱机制。
对Object 对象中 hashCode 和 equals 方法的理解
- equals 方法,用于比较对象的内容是否相等。当子类覆盖了 equals 方法时,比较对象是否相等将通过覆盖后的 equals 方法进行比较(判断对象的内容是否相等)。
- hashCode 方法,大多在集合中用到。如果重写了 equals 方法,就必须重写 hashCode 方法,否则就会降低 Map 等集合的索引速度。
hashCode 方法的重写,可以看看 《科普:为什么 String hashCode 方法选择数字31作为乘子》方法。
讲讲类的实例化顺序
初始化顺序如下:
- 父类静态变量
- 父类静态代码块
- 子类静态变量、
- 子类静态代码块
- 父类非静态变量(父类实例成员变量)
- 父类构造函数
- 子类非静态变量(子类实例成员变量)
- 子类构造函数
Java IO
Java IO 相关的类在java.io
包下,具体操作分成面向字节(Byte)和面向字符(Character)两种方式,如下图所示。
Java提供了哪些IO方式? NIO如何实现多路复用?
首先,传统的 java.io
包,它基于流模型实现,提供了我们最熟知的一些 IO 功能,比如 File 抽象、输入输出流等。交互方式是同步、阻塞的方式,也就是说,在读取输入流或者写入输出流时,在读、写动作完成之前,线程会一直阻塞在那里,它们之间的调用是可靠的线性顺序。
java.io
包的好处是代码比较简单、直观,缺点则是 IO 效率和扩展性存在局限性,容易成为应用性能的瓶颈。
很多时候,人们也把 java.net
下面提供的部分网络 API,比如 Socket、ServerSocket、HttpURLConnection 也归类到同步阻塞 IO 类库,因为网络通信同样是 IO 行为。
第二,在 Java 1.4 中引入了 NIO 框架(java.nio
包),提供了 Channel、Selector、Buffer 等新的抽象,可以构建多路复用的、同步非阻塞 IO 程序,同时提供了更接近操作系统底层的高性能数据操作方式。
第三,在 Java 7 中,NIO 有了进一步的改进,也就是 NIO 2,引入了异步非阻塞 IO 方式,也有很多人叫它 AIO(Asynchronous IO)。异步 IO 操作基于事件和回调机制,可以简单理解为,应用操作直接返回,而不会阻塞在那里,当后台处理完成,操作系统会通知相应线程进行后续工作。
Error和Exception区别
- Error(错误),表示系统级的错误和程序不必处理的异常,是 Java 运行环境中的内部错误或者硬件问题。
- 例如:内存资源不足等。
- 对于这种错误,程序基本无能为力,除了退出运行外别无选择,它是由 Java 虚拟机抛出的。
- Exception(异常),表示需要捕捉或者需要程序进行处理的异常,它处理的是因为程序设计的瑕疵而引起的问题或者在外的输入等引起的一般性问题,是程序必须处理的。Exception 又分为运行时异常,受检查异常。
- RuntimeException(运行时异常),表示无法让程序恢复的异常,导致的原因通常是因为执行了错误的操作,建议终止逻辑,因此,编译器不检查这些异常。
- CheckedException(受检查异常),是表示程序可以处理的异常,也即表示程序可以修复(由程序自己接受异常并且做出处理),所以称之为受检查异常。
反射的用途以及实现
反射主要提供了以下功能:
- 在运行时构造一个类的对象
- 调用类的成员变量和方法
- 生成动态代理
什么是动态代理?
动态代理是设计模式中代理模式的一个分类。代理模式分为静态代理和动态代理。
详细介绍你可以看这篇设计模式之代理模式
Java对象创建的方式
- 使用
new
关键字创建对象 - 使用
Class
类的newIntance
方法(反射机制) - 使用
Constructor
类的newInstance
方法(反射机制)。 - 使用 clone 方法创建对象。
- 使用(反)序列化机制创建对象。
强引用、软引用、弱引用、虚引用(幻象引用)有什么区别?
不同的引用类型,主要提现的是对象不同的可达性(reachable)状态和对垃圾收集的影响。
强引用(Strong Reference)
是我们最常见的普通对象引用,只要还有强引用指向一个对象,就能表明对象还“活着”,垃圾收集器不会碰这种对象。对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显式的将对应(强)引用赋值为null,就是可以被垃圾收集的了,当然具体回收时机还是要看垃圾收集策略。软引用(Sort Reference)
是一种相对强引用弱化一些的引用,可以让对象豁免一些垃圾收集。只有当JVM认为内存不足时,才会去试图回收软引用指向的对象。JVM会确保在抛出OutOfMemoryError之前,清理软引用指向的对象。软引用通常用来实现内存敏感的缓存,如果还有空闲内存,就可以暂时保留缓存,当内存不足时清理掉,这样就保证了使用缓存的同时,不会耗尽内存。弱引用(Weak Reference)
并不能使对象豁免垃圾收集,仅仅是提供一种在弱引用状态下对象的访问途径。这就可以用来构建一种没有特定约束的关系,比如,维护一种非强制性的映射关系,如果试图获取时对象还在,就使用它,否则重新实例化。它同样是很多缓存实现的选择。虚引用,也叫幻象引用
你不能通过它访问对象。虚引用仅仅是提供一种确保对象被finalize以后,做某些事情的机智,比如,通常用来做所谓的Post-Mortem清理机智,也有人利用虚引用监控对象的创建和销毁。