Java 基础总结

1.面向对象与面向过程

面向过程

  • 优势:对程序性能要求比较高,而类调用时开销比较大,比较消耗资源,面向过程开发避免了这一弊端,性能较好
  • 缺点:难维护,难服用,难扩展

面向对象

  • 优势:面向对象有封装、继承、多态特性,能够设计出低耦合的系统,使系统更加灵活易于维护
  • 缺点:性能低于面向过程

2.java语言特色

  1. 简单易学
  2. 面向对象(封装、继承、多态)
  3. 平台无关性(java编译的字节码能够跑在不一样平台上的jvm里)
  4. 可靠性
  5. 安全性(内存自动回收机制防止内存泄漏;异常处理能够中断程序运行;没有指针保护内存数据)
  6. 支持多线程
  7. 支持网络编程
  8. 编译与解释并存(.java文件 -> 编译 -> .class字节码文件 -> 放到jvm虚拟机里解释执行)

3.封装、继承、多态

  • 封装

把一个对象私有化,同时提供一些能够被外界访问的属性的方法。java

  • 继承

  1. 子类拥有父类对象全部的属性和方法(包括私有属性和私有方法),可是父类中的私有属性和方法子类是没法访问的,只是拥有。(内存分析:在一个子类被建立的时候,首先会在内存中建立一个父类对象,而后在父类对象外部放上子类独有的属性,二者合起来造成一个子类的对象。)
  2. 子类能够拥有本身的属性和方法,即功能扩展。
  3. 子类能够用本身的方式实现父类的方法。
  • 多态

程序中定义的引用变量所指向的具体类型和经过该引用变量出发的方法调用在编程时并不肯定,而是在程序运行期间才肯定,即一个引用变量到底会指向哪一个类的实例对象。该引用变量发出的方法调用究竟是哪一个类中实现的方法,必须在由程序运行期间才能决定。编程

在java中有两种形式能够实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中同一方法)。安全

4.接口和抽象类的区别

  1. 接口中全部方法在接口中不能有实现(注:从java8开始接口方法能够有默认实现),而抽象类能够有非抽象的方法。
  2. 接口中除了staticfinal变量,不能有其余变量,而抽象类中则不必定。
  3. 一个类能够有多个接口,但只能实现一个抽象类。接口本身自己能够经过extends关键字扩展多个接口。
  4. 接口方法默认修饰符是public,抽象方法能够有publicprotecteddefault这些修饰符(抽象方法就是为了被重写因此不能使用private关键字修饰)。
  5. 从设计层面来讲,抽象是对类的抽象,是一种模板设计,而接口是对行为的抽象,是一种行为的规范。

    注:在jdk8中,接口也能够定义静态方法,能够直接用接口名调用,实现类和实现是不能够调用的。若是同时出现两个接口,接口中定义了同样的默认方法,则必须重写,否则会报错。网络

5.成员变量和局部变量区别

  1. 从语法形式上看:成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成员变量能够被publicprivatestatic等修饰符所修饰,而局部变量不能被访问控制修饰符static所修饰;可是,成员变量和局部变量都能被final所修饰。
  2. 从变量在内存中的存储方式来看:若是成员变量是使用static修饰的,那么这个成员变量是属于类的,若是没有使用static修饰,这个成员变量是属于实例的。而对象存在与对内存,局部变量则存在于栈内存。
  3. 从变量在内存中的生命周期来看:成员变量是对象的一部分,它随着对象的建立而存在,而局部变量随着方法的调用而自动消失。
  4. 成员变量若是没有被赋初值,则会自动以类型的默认值而赋值(例外:被final修饰的成员变量必须显式地赋值),而局部变量则不会自动赋值。

6.hashCode与equals

  • hashCode介绍

hashCode()的做用是获取哈希码,也成为散列码,它其实是一个int整数。这个哈希码的做用是肯定该对象在哈希表中的索引位置。hashCode()定义在JDK的Object对象中,这就意味着java中全部类的对象都包含该函数。多线程

散列表存储的键值对(key-value),特色是:能根据“key”快速检索出对应的“value”。这其中就利用到了散列码。并发

  • 为何要有hashCode

当你把对象加入HashSet时,HashSet会先计算对象的hashcode值来判断对象加入的位置,同时也会与其余已经加入的对象的hashcode值做比较,若是没有相符的hashcodeHashSet会假设对象没有重复出现。可是若是发现有相同hashcode值的对象,这时会调用equals()方法来检查hashcode相等的对象是否真的相同。若是二者相同,HashSet就不会让其加入操做成功。若是不一样的话,就会从新散列到其余位置。这样咱们就大大减小了equals的次数,相应就大大提升了执行速度。框架

经过咱们能够看出:hashCode()的做用就是获取哈希码,也称为散列码;它其实是返回一个int整数。这个哈希码的做用是肯定该对象在哈希表中的索引位置。hashCode()在散列表中才有用,在其它状况下没用。在散列表中hashCode()的做用是获取对象的散列码,进而肯定该对象在散列表中的位置。异步

  • hashCode与equals相关约定

    1. 若是两个对象相等,则hashCode必定也是相同的
    2. 两个对象相等,对两个对象分别调用equals方法都返回true
    3. 两个对象有相同的hashCode值,它们也不必定是相等的
    4. 所以,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖
    5. hashCode()的默认行为是对堆上的对象产生独特值。若是没有重写 hashCode(),则该类的两个对象不管如何都不会相等(即便这两个对象指向相同的数据)

7.线程的基本状态

状态名称 说明
NEW 初始状态,线程被构建,可是尚未调用start()方法
RUNNABLE 运行状态,Java县城将操做系统中的就绪和运行两种状态笼统地称做“运行中”
BLOCKED 阻塞状态,表示线程阻塞于锁
WAITING 等待状态,表示线程进入等待状态,进入该状态表示但钱县城须要等待其余线程作出一些特定动做(通知或中断)
TIME_WAITING 超时等待状态,该状态不一样于WAITING,它是能够在指定的时间自行返回
TERMINATED 终止状态,表示当前县城已经执行完毕

8.Java中的异常处理

Java异常类层次结构图

Java异常类层次结构图

在 Java 中,全部的异常都有一个共同的祖先java.lang包中的 Throwable类。Throwable: 有两个重要的子类:Exception(异常)Error(错误) ,两者都是 Java 异常处理的重要子类,各自都包含大量子类。jvm

Error(错误):是程序没法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操做无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,Java虚拟机运行错误(Virtual MachineError),当 JVM 再也不有继续执行操做所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)通常会选择线程终止。函数

这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。这些错误是不可查的,由于它们在应用程序的控制和处理能力之 外,并且绝大多数是程序运行时不容许出现的情况。对于设计合理的应用程序来讲,即便确实发生了错误,本质上也不该该试图去处理它所引发的异常情况。在 Java中,错误经过Error的子类描述。

Exception(异常):是程序自己能够处理的异常。Exception 类有一个重要的子类RuntimeException。RuntimeException 异常由Java虚拟机抛出。NullPointerException(要访问的变量没有引用任何对象时,抛出该异常)、ArithmeticException(算术运算异常,一个整数除以0时,抛出该异常)和 ArrayIndexOutOfBoundsException(下标越界异常)。

注意:异常和错误的区别:异常能被程序自己能够处理,错误是没法处理。

Throwable类经常使用方法

  • public string getMessage():返回一场发生时的详细信息
  • public string toString():返回一场发生时的简要描述
  • public string getLocalizedMessage():返回一场对象的本地化信息。使用Throwable的子类覆盖这个方法,能够声称本地化信息。若是子类没有覆盖该方法,则该方法返回的信息与getMessage()返回的结果相同
  • public void printStackTrace():在控制台上打印Throwable对象封装的异常信息

异常处理总结

  • try 块:用于捕获一场。其后可接零个或多个catch块,若是没有catch块,则必须跟一个finally块。
  • catch 块:用于处理try 捕获到的异常。
  • finally 块:不管是否捕获或处理异常,finally 块里的语句都会被执行。当在try 块或catch 块中遇到return 语句时,finally 语句块将在方法返回以前被执行。

在一下4种特殊状况下,finally 块不会被执行

  1. 在finally 语句块第一行发生了异常,由于在其余行,finally 块仍是会获得执行
  2. 在前面的代码中用了System.exit(int)已退出程序。exit是带参函数;若该语句在异常语句以后,finally 会执行
  3. 程序所在的线程死亡
  4. 关闭CPU

关于返回值

若是try 语句里有return,返回的是try 语句块中变量值。详细执行过程以下:

  1. 若是有返回值,就把返回值保存到局部变量中;
  2. 执行jsr指令跳到finally 语句里执行;
  3. 执行完finally 语句后,返回以前保存在局部变量表里的值;
  4. 若是try,finally 语句里均有return,忽略try 的return,而使用finally的return。

9.Java中IO流

java中IO流分为几种?

  • 按照流的流向分,能够分为输入流和输出流
  • 按照操做单元划分,能够划分为字节流和字符流
  • 按照刘的角色划分,能够划分为节点流和处理流

Java IO流共涉及40多个类,这些类看上去很杂乱,但实际上颇有规则,并且彼此之间存在很是紧密的联系,Java IO流的40多个类都是从以下4个抽象类基类中派生出来的。

  • InputStream/Reader:全部的输入流的基类,前者是字节输入流,后者是字符输入流。
  • OutputStream/Writer:全部输出流的基类,前者是字节输出流,后者是字符输出流。

按操做方式分类结构图:

按操做方式分类结构图

按操做对象分类结构图:

按操做对象分类结构图

BIO,NIO,AIO有什么区别?

  • BIO (Blocking I/O): 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动链接数不是特别高(小于单机1000)的状况下,这种模型是比较不错的,可让每个链接专一于本身的 I/O 而且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池自己就是一个自然的漏斗,能够缓冲一些系统处理不了的链接或请求。可是,当面对十万甚至百万级链接的时候,传统的 BIO 模型是无能为力的。所以,咱们须要一种更高效的 I/O 处理模型来应对更高的并发量。
  • NIO (New I/O): NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了NIO框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。NIO中的N能够理解为Non-blocking,不单纯是New。它支持面向缓冲的,基于通道的I/O操做方法。 NIO提供了与传统BIO模型中的 SocketServerSocket 相对应的 SocketChannelServerSocketChannel 两种不一样的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持同样,比较简单,可是性能和可靠性都很差;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可使用同步阻塞I/O来提高开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发
  • AIO (Asynchronous I/O): AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的IO模型。异步 IO 是基于事件和回调机制实现的,也就是应用操做以后会直接返回,不会堵塞在那里,当后台处理完成,操做系统会通知相应的线程进行后续的操做。AIO 是异步IO的缩写,虽然 NIO 在网络操做中,提供了非阻塞的方法,可是 NIO 的 IO 行为仍是同步的。对于 NIO 来讲,咱们的业务线程是在 IO 操做准备好时,获得通知,接着就由这个线程自行进行 IO 操做,IO操做自己是同步的。查阅网上相关资料,我发现就目前来讲 AIO 的应用还不是很普遍,Netty 以前也尝试使用过 AIO,不过又放弃了。
相关文章
相关标签/搜索