Java基础

Java基础

Java development notes document

Source Code

关键字汇总

访问控制 修饰符 程序控制 错误处理 基本类型 变量引用 包相关 保留字
private class for try boolean new package const
protected abstract break catch byte super import go
default(缺省) extends continue finally char this
public implements do throw short void
interface while throws int null
final if long true
strictfp else float false
static switch double
synchronized case
transient default
volatile instanceof
native return
enum assert

基本数据类型

数据类型 boolean byte char,short int long float double
所占字节 见下 1字节 2字节 4字节 8字节 4字节 8字节

boolean到底占几个字节,依赖于JVM:

  1. 无论boolean占用多少字节,只有1bit的值是有意义的;
  2. boolean类型被编译成int类型来使用,占4个字节;
  3. 在Java虚拟机中,1表示true,0表示false。
  • 在java中整数的默认数据类型是int,例如数字4,小数的默认数字类型是double。当float a = 3.12时会报错,因为3.12的默认数据类型是double。
  • 由于boolean的特殊含义,boolean类型与其他基本类型不能进行类型的转换(既不能进行自动类型的提升,也不能强制类型转换), 否则,将编译出错
  • 类型自动提升:byte/char/short—>int—>long—>float—>double;反之,需要强制转换

final关键字

  • 修饰常量,可以放在方法体里面
  • 修饰类,不能被继承
  • 修饰方法,子类不能重写这个方法
  • 修饰参数,这个参数不能被修改,如果这个参数是类对象,可以调用该对象的set方法

transient

Java序列化

Java序列化就是把一个对象保存到一个文件或字节流中去,反序列化就是在适当的时候把这个文件再转化成原来的对象使用。

序列化和反序列化最主要的作用有:

  • 在进程下次启动时读取上次保存的对象的信息,例如读取session内容;
  • 在不同的进程之间传递数据;
  • 在分布式应用系统中传递数据?

Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。

将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以用来在内存中新建对象。

整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。

ObjectInputStreamObjectOutputStream 是高层次的数据流,它们包含反序列化和序列化对象的方法。

在实际开发过程中,会遇到这样的问题,某个类的有些属性需要序列化,而其他属性不需要被序列化;例如:如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。

总之,java 的transient关键字为我们提供了便利,只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中

transient使用

  • 一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
  • transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类成员变量,想用transient修饰,则该类需要实现Serializable接口。
  • 被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化

transient细节

被transient关键字修饰的变量真的不能被序列化吗?

在Java中,对象的序列化可以通过实现两种接口来实现,若实现的是Serializable接口,则所有的序列化将会自动进行,若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关

Externalizable接口继承了Serializable接口,用来在序列化时手动地把需要的对象信息进行序列化。

strictfp关键字

关键字strictfp是strict float point的缩写,指的是精确浮点,是用来确保浮点数运算的准确性。

JVM在执行浮点数运算时,如果没有指定strictfp关键字,此时计算结果可能会不精确,而且计算结果在不同平台或厂商的虚拟机上会有不同的结果,导致意想不到的错误。

而一旦使用了strictfp来声明一个类、接口或者方法,那么在所声明的范围内,Java编译器以及运行环境会完全依照IEEE二进制浮点数算术标准来执行,在这个关键字声明的范围内所有浮点数的计算都是精确的。

需要注意的是,当一个类被strictfp修饰时,所有方法都会自动被strictfp修饰。strictfp可以保证浮点数运算的精确性,而且在不同的硬件平台会有一致的运行结果。

程序的错误类型

程序的错误可以抽象分为三类:语法错误、运行错误和逻辑错误。

  • 语法错误
    • 由于编程中输入不符合语法规则而产生的。程序编译就通不过,程序不能运行起来。
  • 运行错误
    • 程序在运行过程中出现的错误。程序通过语法错误检测,但是运行的时候出现错误,导致程序被迫终止,此类错误有特定的发生条件,因此能够准确的定位错误代码段,因而调试也比较方便。例如:除0操作。
  • 逻辑错误
    • 程序运行后,没有得到设计者预期的结果,这就说明程序存在逻辑错误。这种错误在语法上是有效的,但是在逻辑上是错误的。

异常类型

部分异常类的依赖图

  • 自己也可以自定义异常实现。

  • Throwable有两个子类,Error和Exception。

    • 其中Error是错误,对于所有的编译时期的错误以及系统错误都是通过Error抛出的。这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。在 Java中,错误通过Error的子类描述。
    • Error的出现表示运行应用程序中较严重问题。必须解决,处理方式:只能抛出
  • Exception,是另外一个非常重要的异常子类。它规定的异常是程序本身可以处理的异常。异常和错误的区别是,异常是可以被处理的,而错误是没法处理的。

  • Checked Exception

    可检查的异常,这是编码时非常常用的,所有checked exception都是需要在代码中处理的。它们的发生是可以预测的,正常的一种情况,可以合理的处理。比如IOException,或者一些自定义的异常。除了RuntimeException及其子类以外,都是checked exception。

  • Unchecked Exception

    RuntimeException及其子类都是unchecked exception。比如NPE空指针异常,除数为0的算数异常ArithmeticException等等,这种异常是运行时发生,无法预先捕捉处理的。Error也是unchecked exception,也是无法预先处理的。

  • 为什么要创建自己的异常?

    当Java内置的异常都不能明确的说明异常情况的时候,需要创建自己的异常。

  • throw和throws的区别?

    • throw后面跟异常对象;throws后面跟异常类名

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      // throws跟在方法声明后面,后面跟的是异常类名
      public void method() throws ArithmeticException {
      int a=10;
      int b=0;
      if(b==0) {
      // throw用在方法体内,后面跟的是异常类对象名
      throw new ArithmeticException();
      }else {
      System.out.println(a/b);
      }
      }
  • throw后面只能跟一个对象;throws后面可以跟多个类名,用逗号隔开

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // throws跟多个异常类名,用逗号隔开
    public static void method() throws ArithmeticException,Exception {
    int a=10;
    int b=0;
    if(b==0) {
    // 只能抛出一个异常对象名
    throw new ArithmeticException();
    }else {
    System.out.println(a/b);
    }
    }
  • throw在方法内部使用;throws在方法签名上使用

  • throw表示抛出异常,由该方法体内的语句来处理;throws表示抛出异常,由该方法的调用者来处理

  • throw抛出异常,执行throw一定出现了某种异常;throws表示有出现异常的可能性,并不一定出现这些异常

为什么会有GC机制?

  • 安全性考虑
  • 减少内存泄露
  • 减少程序员工作量

JVM内存结构

评论