Java基础

40 阅读5分钟

1.概念基础

  • 一、面向对象:
    • 开发首先要明确每个功能现实中使用的对象是谁。
    • 代码中的面向对象指每个行为都是有一个主体作为对象来实现的。
  • 二、常说的java三大特性:封装、继承、多态
    • 封装,通过private控制外部访问途径,提高可控性和可维护性。
    • 继承,通过extands继承你不想重写的代码并增加不应该给父类的功能,若一些方法常被多个子类实现时一般会定义接口,此外还有抽象类通过继承让子类实现抽象方法提高维护性。
    • 多态,通过入参不同重载同名方法以及通过重写覆盖父类的方法实现自己的行为。
  • 三、反射:一般来说使用的场景,编译时无法预知该对象和类可能属于哪些类,只能依靠运行时信息来发现该对象和类的真实信息。
  • 四、接口:提供公用的方法,规定子类的行为。子类通过implements必须实现接口中定义的所有方法。

2. 代码基础

  • 一、数据类型:包装类型,基础类型
    • 基础类型:byte(8位有符号整数-128到127)、short(16位)、int(32位)、long(64位)、float(32位有符号浮点数,指数占8bit)、double(64位有符号浮点数,指数占11bit)、boolean、char(单一16位Unicode字符)、String
    • 浮点数:具体参考IEEE754浮点数标准,有一些优化的规定。
      • 浮点数转换二进制过程会有循环导致溢出,造成精度损失,不可用于货币存储
      • 浮点数0.2转换为二进制数的过程为,不断乘以2,直到不存在小数为止,在这个计算过程中,得到的整数部分从上到下排列就是二进制的结果,循环会导致无限,导致占位溢出。
    • 强制类型转换:容量大的类型使用括号强制转换时,不在容量范围内的值会溢出,比如byte b=(byte)128,此时由于比范围127大,值会溢出1结果为-128。具体是二进制转换自动将溢出的位丢弃了导致的。
    • 包装类型:Byte、Short、Integer、Long、Float、Double、Boolean、Character
      • 包装类型是对基本类型的包装,使其拥有对象的性质,存储于堆而非基本类型的堆栈。包装类型可以自动拆箱,包装类内有缓存一定范围的值
  • 二、关系和逻辑运算符:
    • ==判断是否相等,面试中常和equal做比较。
      • 当==用于基本数据类型,判断值;当==用于引用数据类型和字符串,不比值比较内存地址
      • eaqul只能用于引用对象和字符串的比较,字符串比较值,引用对象没重写默认比较内存地址。
    • &&运算符两边都成立结果为true,当左边不为true不会继续右边的计算。
    • instanceof运算符左侧类型是否兼容右侧特定类型,父类兼容自身和子类。
    • ?:三目运算符,用于简化选择操作。
  • 三、常见关键字:
    • final
      • 变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销。被final标识的字符串会进入常量池,值不可变,被final标识的方法不可重写,被final标识的引用对象仅表示不可变更指向,内容可变
    • static
      • 方便在没有创建对象的情况下进行调用(方法/变量),但需要类被加载。
      • 静态变量被所有对象共享,在内存中只有一个副本,在类初次加载的时候才会初始化。
      • 静态方法由于可以没有对象,所以无法调用非静态方法和非静态变量。
      • 不会被虚拟机GC回收掉,内存压力大。
    • synchronized
      • 本质是对象锁,通过竞争获取对象,底层存在一个monitor,每个被加锁的对象都会有一个,字节码获取锁时执行 monitorenter,如果计数器为0说明可以成功获取锁,计数器现在是1,否则就阻塞。
      • 1.对于普通同步方法,锁是当前实例对象。
      • 2.对于静态同步方法,锁是当前类的Class对象。
      • 3.对于同步方法块,锁是synchronized括号里配置的对象。
      • synchronized会自动释放锁
    • volatile
      • 只能保证可见,不能保证原子性!
      • 不能保证线程安全!!!
      • 使共享变量线程可见,会禁止指令重排序。
      • 通过总线嗅探机制感知到缓存中数据的变化并将工作内存中的数据失效,保证当自己修改时数据是最新的,而不是直接使用自己的处理器缓存。大量使用会引起嗅探总线风暴。
      • 最终解析的汇编指令会在指令前加上lock前缀指令来保证工作内存中读取到的数据是主内存中最新的数据。
      • 假设现在有N个线程对同一个变量进行累加也是没办法保证结果是对的,因为读写这个过程并不是原子性的,只能对写操作加锁。
      • 部分适用场景:一次性安全发布(双重检查单例),一次性状态变更,独立观察(定期 “发布” 观察结果供程序内部使用)。