java基础数据类型(8种)

  • 字符型:char(2个字符)
  • 布尔类型:boolean(1个字符)
  • 整数型:byte(1个字符)、 short(2个字符)、 int(4个字符)、 long(8个字符)
  • 浮点型:float(4个字符)、 double(8个字符)


修饰符

  • public:对所有类可见;可以修饰类、接口、方法、变量;
  • protected:对同一包内的类和所有子类可见;可以修饰变量、方法,不可以修饰类;
  • default:在同一包内可见;可以修饰类、接口、方法、变量;
  • private:在同一类内可见;可以修饰变量、方法;不可以修饰类。

补充

  1. 不可以继承父类的私有对象或者方法;但是可以通过共有的方法访问私有的对象。
  2. 权限大小:public --> protected --> default --> private


java关键字

static

  • 存放在方法区中;
  • 修饰变量,表示为静态变量,被所有对象共享,在内存只有一个副本,当且仅当类初次加载时会被初始化(类加载过程的准备阶段)
  • 修饰方法,表示为静态方法,可以使用类名直接访问,不依赖于任何对象,既然没有对象也就谈不上this了;静态方法不能访问非静态方法,非静态方法可以访问静态方法
  • 修饰代码块,表示为静态代码块可以优化程序性能,会按照静态代码块-->构造函数的顺序执行,只会在类加载的时候执行一次所以优化了性能。

final

基础

  • 修饰变量,表示为基础数据类型不能更改值;对象数据类型不能修改指向,但是可以修改内容
  • 修饰方法,表示这个方法不能被子类继承重写,但是可以被重载;其中,private方法会被隐式的指定为final方法
  • 修饰类:表示这个类不能被继承,这个类的所有的成员变量可根据需要设定为final、成员方法会被隐式的设定为final;例如:String类就是一个final类。

常见问题

如何对final类进行拓展,增添新的方法?
  • 由于final修饰类不能继承,所以可以通过组合来实现;
例如复用String类
/**
* @pdai
*/
class MyString{

    private String innerString;
    
    // ...init & other methods

    // 支持老的方法
    public int length(){
        return innerString.length(); // 通过innerString调用老的方法
    }

    // 添加新方法
    public String toMyString(){
        //...
    }
}


final的赋值?
  • 在定义处进行赋值;
  • 构造器中进行赋值,保证了该值在被使用前赋值。

final域重排序规则

避免因为指令重排序带来的可见性问题

  1. 写final域重排序规则:保证在对象引用为任意线程可见之前,对象的final域已经被正确初始化
  • 编译器会在final域写之后,构造函数return之前,插入一个storestore屏障。这个屏障可以禁止处理器把final域的写重排序到构造函数之外。
  • 在构造函数内对一个final修饰对象的成员域的写入,与随后在构造函数之外把这个被构造的对象的引用赋给一个引用变量,这两个操作不能被重排序。
总结

写final域重排序规则


  1. 读final域重排序规则:保证在读取一个对象的final域之前,一定会先读这个包含这个final域的对象的引用
  • 在一个线程中,初次读取对象引用和初次读取对象包含的final域,JMM会禁止这两个操作的重排序;
  • 处理器会在读final域操作的前面插入一个LoadLoad屏障。

缺陷:

final域写重排序规则可以确保我们在使用一个对象引用的时候,该对象的final域已经在构造函数被初始化过了。但是需要有一个前提,“在构造函数,不能让这个被构造的对象被其他线程可见,也就是说该对象引用不能在构造函数中溢出

解释:

由于对构造函数this溢出、初始化final域之间并没有数据依赖,可以重排;那么先执行构造函数溢出,此时溢出的对象是没有完全初始化的对象(final域还没有初始化),那么当执行到final域的时候就会因为没有初始化出错。

构造函数溢出


参考



Object类

  • clone:浅拷贝,只会拷贝对象的引用地址,而不会将引用对象重新分配内存;
  • getClass:返回类实例;
  • toString:返回该对象的字符串;
  • finalize:用于释放资源,现在常用四个引用类型替代;参考:引用;
  • equals
  • hashCode
  • wait
  • notify
  • notifyAll


异常机制

java通过Throwable类中的众多子类描述不同的异常

层次结构

包含:Error(错误) 和 Exception(异常) 异常

Error

  • 程序中无法处理的错误,表示运行应用程序中出现了严重的错误;
  • 是不受检异常、非代码错误;
  • 例如:OutOfMemoryError(内存不足)、OutOfMemoryError(栈溢出)

Exception

运行时异常
  • 一般由程序逻辑错误引起的,java编译器不会检查它;
  • 都是RuntimeException类及其子类异常;
  • 例如:NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)
编译异常
  • 程序必须进行处理的异常,如果不处理,程序就不能编译通过;
  • 例如:IOException、SQLException


值传递与引用传递

值传递

  • 主要在栈上分配内存空间
  • 是指在调用函数时,将实际参数复制一份传递到函数中,这样在函数如果对参数进行修改,不会影响到实际参数值传递
代码实现
package com.hshuo;

/**
 * @author SHshuo
 * @data 2022/5/19--8:25
 * 值传递与引用传递
 */
public class transmit {
    public static void main(String[] args) {

//        值传递、不会修改原数据
        int number = 10;
        new transmit().change(number);
//        输出仍未10
        System.out.println(number);
    }

    private void change(int number) {
        number += 1;
    }
}


引用传递

  • 引用变量在栈中,实际对象在堆中;引用变量指向实际对象
  • 是指在调用函数时,将实际参数的地址传递到函数中,函数对参数的修改会影响到实际参数引用传递
代码实现
package com.hshuo;

/**
 * @author SHshuo
 * @data 2022/5/19--8:25
 * 值传递与引用传递
 */
public class transmit {
    public static void main(String[] args) {

//        引用传递
        User user = new User("hshuo", 21);
        System.out.println(user.getName());
        new transmit().changeAgain(user);
//        修改原先的值
        System.out.println(user.getName());
    }

    private void changeAgain(User user) {
        user.setName("lmz");
    }
}



面向对象三大特征

  • 封装:将一些实体类、工具类封装、提高软件的可重用性;
  • 继承:继承应该遵循里氏替换原则,子类对象必须能够替换掉所有父类对象;获得父类非 private 的属性和方法,private属性修饰的变量,可以通过Public的getter、setter方法暴露出来;
  • 多态:多个子类继承父类,根据不同需要重写里面的方法,体现多态。

拓展



== 与 equals的区别

==

  • 基础数据类型:比较的值
  • 引用数据类型:比较内存地址

equals

  • 默认在Object里面,相当于 == 但是一般使用前会重写equals方法,用于值的比较。


重载 与 重写的区别

重写

在继承体系中,指子类实现一个与父类在方法声明上完全相同的一个方法。同时应该满足里式替换原则,重写有以下两个限制:

  1. 子类方法的访问权限必须 >= 父类方法
  2. 子类方法返回类型必须 >= 父类方法返回类型;

重载

  • 存在于同一个类中,指一个方法与已经存在的方法名称上相同,但是参数类型、个数、顺序至少有一个不同
  • 注意:返回值不同,其他都相同不算重载


String、 StringBuilder、 StringBuffer的区别

String

  1. String类被final修饰,不可以被继承
  2. 内部使用char数组存储数据,并且被final修饰,意味着value数组初始化之后不能再引用其他数组;保证了String 不可变

也就是说每次对String类型进行改变的时候其实相当于生成一个新的String对象,然后将指针指向新的String对象,GC回收旧的String对象。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

StringBuilder、 StringBuffer

  • StringBuffer线程安全,使用Synchronized修饰
  • StringBuilder线程不安全
  • 二者都是可变的,value数组没有被final修饰

参考:Synchronized