八大数据类型:

  • 字节型
    • byte(Byte)/8
  • 浮点型
    • float(Float)/32
    • double(Double)/64
  • 布尔型
    • boolean(Boolean)/~
  • 字符型
    • char(Character)/16
  • 整型
    • short(Short)/16
    • int/(Integer)32
    • long(Long)/64
  • boolean 只有两个值:true,false。可以使用1bit来存储。但是具体大小没有明确规定。
  • JVM会在编译时期把boolean类型转换为int,true=1,false=0,java支持boolean数组但是是通过byte数组来实现的。

包装类型:

    • Integer x=2;自动装箱:Integer.valueOf(2)
    • int y=x;自动拆箱:X.intValue()

缓存池:

new Integer(123) 与 Integer.valueOf(123) 的区别在于:

  • new Integer(123) 每次都会新建一个对象;
  • Integer.valueOf(123) 会使用缓存池中的对象,多次调用会取得同一个对象的引用。

IntegerCache缓存池默认是-128-127

也可以在JVM中修改上限 XX:AutoBoxCacheMax=<size>来指定上限大小。

String:

  • java8中String是由final修饰,char数组
  • java9中用byte数组并使用coder标识使用了哪种编码
  • value数组被声明成final,这意味着value初始化以后就不能被修改了,因此保证了不可变性。

String用final修饰的好处:

  • 可以缓存哈希值
    • 因为String的hash经常被使用,比如HashMap中的key,不可变特性保证了只计算一次和hash值不变。
  • StringPool的需要
    • 如果一个String对象被创建过了,那么就会从StringPool中取得引用,只有String是不可变的,才可能使用StringPool。
  • 安全性
    • String 经常作为参数,String的不可变性保证了参数的不可变性。
  • 线程安全
    • 不可变性,天生具备线程安全。

String,StringBuffer,StringBuilder区别

  • 可变性
    • String不可变
    • StringBuffer和StringBuilder可变
  • 线程安全
    • String线程安全
    • StringBuffer线程安全(内部使用了Synchronized同步)
    • StringBuilder线程不安全

StringPool

  • 字符串常量池(StringPool), 保存着所有字符串字面量,这些字面量在编译时期就确定,不仅如此还能使用String的intern()方法在运行过程中向StringPool中插入新的字符串。
  • 当一个字符串调用intern()方法时,如果StringPool中已经存在一个字符串通过equals比较相等。那么就会返回StringPool中的引用,否则创建一个新的,返回新的引用。
  • 简而言之String中的intern方法就是StringPool中如果有这个字符串就返回这个字符串的引用,如果没有,就新建一个然后返回新的引用。
  • java7之前中StringPool被放到常量池中也就是永久代,java7之后放到堆中,因为永久代空间有限,大量字符串被创建容易出现OOM。

new String(“ABC”)

  • 使用这种方式一共会创建两个对象(前提是Stringpool中没有ABC的对象)
  • “ABC”输入字符串字面量,因此会在StringPool中创建一个字符串对象,指向这个ABC字符串字面量
  • 而使用new会在堆中创建一个对象。

运算

  • 参数传递
    • java的参数是以值传递的形式传入到方法中,而不是引用传递。
  • float和double
    • java不能隐式的执行向下转型,因为这会使得精度降低
    • 字面量属于double类型,不能直接将1.1直接赋值给float,因为这是向下转型。
    • 1.1f才是float类型
  • 隐式类型转换
    • 字面量1是int类型,不能直接使用short转换
    • short s1 = 1; // s1 = s1 + 1;
    • 但是可以使用++,--,或者强转。

switch

  • 从java7开始,可以使用switch的条件判断语句使用String对象
    • String s = "a"; switch (s) { case "a": System.out.println("aaa"); break; case "b": System.out.println("bbb"); break; }
  • Switch不支持long,因为switch的设计初衷就是针对少数几个值的类型进行等值判断。如果过于复杂还是用if比较合适。

关键字

  • final
    • 数据
      • 声明数据时为常量,可以是编译时常量也可以是运行时初始化后就不能被修改的常量。
      • 对于基本类型,final使数值不变
      • 对于引用类型,final使引用不变,也就是不能引用其他对象,但是被引用的对象可以修改。
    • 方法
      • 方法不能被子类重写。
      • private的方法隐式的被指定为final,如果在子类中定义一个方法和基类中的一个private签名相同,此时子类的方法不是重写,而是一个新的方法。
    • 不能被继承。
  • static
    • 静态变量
      • 静态变量:又叫类变量,也就是说这个变量属于类,类中的所有实例都可以通过类名访问该静态变量,在内存中值存一份。
      • 实例变量:每创建一个实例,就会产生一个实例变量,它与该实例同生死。
      • public class A { private int x; // 实例变量 private static int y; // 静态变量 public static void main(String[] args) { // int x = A.x; // Non-static field 'x' cannot be referenced from a static context A a = new A(); int x = a.x; int y = A.y; } }
      • 静态方法
        • 静态方法在类加载的时候就已经存在了,它不依赖于任何实例,所以静态方法必须有实现,也就是说不能是抽象方法。
        • public abstract class A { public static void func1(){ } // public abstract static void func2(); // Illegal combination of modifiers: 'abstract' and 'static' }
        • 只能访问所属类的静态字段和静态方法,方法中不能有this,和super关键字,因为这两个关键字与具体对象关联。
      • 静态语句块
        • 静态语句块在类初始化的加载一次。
      • 静态内部类
        • 非静态内部类创建依赖于外部类实例,也就是说只有外部类实例创建后才能创建非静态内部类,静态内部类不需要。
        • 静态内部类不能外部类的非静态方法和非静态变量。
      • 静态导包
      • 初始化顺序
        • 静态变量和静态语句块优先于实例变量和普通语句块,静态变量和静态语句块的初始化顺序取决于它们在代码中的顺序。
        • 存在继承的情况下,初始化顺序为:
  • 父类(静态变量、静态语句块)
  • 子类(静态变量、静态语句块)
  • 父类(实例变量、普通语句块)
  • 父类(构造函数)
  • 子类(实例变量、普通语句块)
  • 子类(构造函数)

Object方法

  • equals
    • 等价关系
      • 自反性
      • 对称性
      • 传递性
      • 一致性
      • 与null的比较
    • 等价与相等
      • 对于基本类型,==判断两个值是否相等,基本类型没有equals方法
      • 对于引用类型,==判断是否引用同一个对象,equals引用的对象是否等价。
    • 实现
      • 检查是否为同一个对象的引用如果是直接true
      • 检查是否为同一类型,如果不是直接false
      • 将object对象进行转型
      • 判断每个关键域是否相等
      • public class EqualExample { private int x; private int y; private int z; public EqualExample(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; EqualExample that = (EqualExample) o; if (x != that.x) return false; if (y != that.y) return false; return z == that.z; } }
      • hashCode()
        • hashCode()返回hash值,而equals是用来判断两个对象是否是等价,等价的对象散列值一定相同,但是散列值相同的两个对象不一定等价,这是因为计算哈希值具有 随机性,两个值不同的对象可能计算出相同的哈希值。
        • 在覆盖equals方法时,应当总是覆盖hashCode()方法,保证等价的两个对象的hash值也相等。
        • hashSet和HashMap等集合类使用hashCode来计算对象应该存储的位置,因此要将对象添加到集合类需要将对应的对象添加hashCode方法。
        • 理想的哈希函数应道具有均匀性,不相等的对象应当均匀地分布在所有可能的hash值上,这就要求hash函数要将所有域的值考虑进来,可以把每个域都当成R进制的某一位,然后组成一个R进制的整数。
        • R一般是31,奇素数。偶数会溢出,信息丢失。
      • toString
        • 默认返回 ToStringExample@4554617c 这种形式,其中 @ 后面的数值为散列码的无符号十六进制表示
      • clone
        • cloneable
        • clone是Object的projected函数,他不是public,一个类不显示的去重写clone,其他类就不能直接去调用该类实例的clone方法。
        • 重写clone方法,必须实现cloneable接口,这只是一个接口规范,如果一个类没有实现CloneAble接口,又重写了clone方***抛出异常,CloneNotSupportedException。
      • 浅拷贝
        • 拷贝对象和原始对象的引用类型是同一对象。
      • 深拷贝
        • 拷贝对象和原始对象引用类型不是同一对象
      • clone的替代方案
        • 使用clone方法来拷贝一个对象不好,会抛出异常还有类型转换。
        • 可以使用拷贝 构造函数和拷贝工厂来拷贝一个对象

继承

  • 访问权限
    • private,projected,public,default
    • 抽象类和接口
      • 抽象类:使用abstract修饰,一个类中包含抽象方法那么这个类必须声明为抽象类。
      • 抽象类和普通类的最大区别是抽象类不能被实例化,只能被继承。(extends)
      • 接口(interface使用implements实现)
        • java8之前可以看成完全抽象的抽象类,java8以后可以拥有默认的方法,接口成员默认public,字段默认static,final。
    • 比较
      • 从设计层面抽象类是一种IS-A方式,需要满足里式替换原则,子类必须能够替换所有的父类对象
      • 接口是LIKE-A,只提供方法实现契约,不要求IS-A关系。
      • 一个类可以实现多个接口,只能继承一个抽象类
      • 接口中成员方法只能是public,字段是static final,而抽象类可以是其他的。
    • 使用选择:
      • 接口
      • 需要让不相关的类都实现一个方法,例如不相关的类都可以实现Compareable接口中的compareTO方法。
      • 需要多重继承。
      • 抽象类
      • 需要在几个相关类***享代码
      • 需要控制访问权限
      • 需要继承非静态和非常量的字段
    • 大多数情况下接口优于抽象类,在很多情况下,接口优先于抽象类。因为接口没有抽象类严格的类层次结构要求,可以灵活地为一个类添加行为。并且从 Java 8 开始,接口也可以有默认的方法实现,使得修改接口的成本也变的很低。

super

访问父类的构造函数:可以使用 super() 函数访问父类的构造函数,从而委托父类完成一些初始 化的工作。应该注意到,子类一定会调用父类的构造函 数来完成初始化工作,一般是调用父类的默认构造函数,如果子类需要调用父类其它构造函数,那么就可以使用 super() 函数。访问父类的成员:如果子类重写了父类的某个方法,可以通过使用 super 关键字来引用父类的方法实现。

重写与重载

  • 重写Override
    • 存在于继承体系,指子类实现了一个与父类在方法声明上完全相同的方法。
    • 为了满足里式替换原则,重写有三个限制:
      • 子类方法访问权限必须小于等于父类
      • 返回类型必须相等或者是子类型
      • 抛出异常,相等或者子类。
    • 使用 @Override 注解,可以让编译器帮忙检查是否满足上面的三个限制条件。
    • 调用顺序优先级
      • 先找自己的
      • 找不到,然后找父类的
      • 在找不到,参数转型成父类的找自己
      • 再找不到,参数转成父类,找父类。
    • this.func(this)

super.func(this)

this.func(super)

super.func(super)

  • 重载Overload
    • 存在于同一个类中,方法名称相同,但是参数类型,顺序,个数至少有一个不同
    • 返回值不同,其他都相同的不算重载,有二义性。

反射

  • 每个类都有一个Class对象,包含着与类有关的信息,当编译一个新类时,会产生一个同名的.class文件,该文件内容保存着Class对象。
  • 类加载,相当于Class加载,类在第一次使用时才动态的加载到JVM中,也可以使用Class.forName("com.mysql.jdbc.Driver")控制类加载,会返回一个Class对象。
  • 反射可以提供运行时类信息
  • Class和java.lang.reflect一起对反射提供支持,java.lang.reflect类库,主要包括以下三个类:
  • Field:可以使用get()和set()方法读取和修改Field对象关联的字段。
  • Method:可以使用invoke调用与Method对象关联的方法。
  • Constructor:可以使用Constructor的newInstance()创建新的对象。

反射优点:

  • 可扩展性:应用程序可以利用全限定名创建可扩展对象实例
  • 类浏览器和可视化开发环境
  • 调试器和测试工具

反射缺点:

  • 性能开销
  • 安全限制:必须在没有安全限制的环境使用反射
  • 内部暴露:私有属性可以被暴露

异常

  • Throwable分为Error和Exception,其中error表示JVM无法处理的错误
  • Exception分为受检时异常和未受检时异常
  • 受检时异常:需要用try-catch 捕获处理
  • 非受检时异常:程序运行时的错误,比如RuntimeException和IOException

 

  • 关键字:
  • throws,try,catch,finallt,throw.

泛型

  • 泛型是什么,使用泛型的好处?
    • 类的参数化,好处是提供了编译时的安全,避免出现类型转换异常。提高复用。
  • 泛型是如何工作的,什么是类型擦除?
    • 泛型是通过类型擦除来实现的,编译器在编译时擦除了所有类型相关信息,所以在运行时不存在任何类型的信息,例如在List<String>,在运行时仅用一个List来表示,这样做的目的是确保和java5之前的版本开发二进制类库进行兼容,你无法在运行时访问到类型参数,因为编译器已经把泛型转换成了原始类型。
  • 什么是泛型中的限定通配符和非限定通配符?
    • 限定通配符分为两种:
      • <?extends T> 它通过确保类型必须是T的子类,确保类型的上界,可以get元素
      • <? super T>它通过确保类型必须是T的父类,来确保下界。可以add元素
      • <?>表示非限定通配符,因为<?>可以被任意类型替代。
  • List<? extends T> 和List<? super T>区别?
    • 第一个可以接受任何父类是T的List
    • 第二个可以接受任何子类是T的List
  • 如何编写一个泛型方法,让他能够接受泛型参数并返回泛型类型?
    • 需要用泛型类型替代原始类型
      • KV, TE,类型占位符。
  • java中如何使用泛型编写带有参数的类?
    • 关键仍然是使用泛型类型来代替原始类型,而且要使用JDK中采用的标准占位符。
  • 编写一段泛型程序来实现LRU缓存?
    • LinkedHashMap可用来实现固定大小的LRU缓存
  • 你可以把List<String>传递给一个接受List<Object>参数的方法吗?
    • 不可以,Object可以存任何对象,String只能存String。
  • Array中可以用泛型吗?
    • 不可以,Array不支持泛型,所以建议使用List来替代Array.
  • 如何阻止java中类型未检查的警告?
    • List<String> rawList = new ArrayList()

https://cloud.tencent.com/developer/article/1178629

注解

  • Java 注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。

注解 Annotation 实现原理与自定义注解例子

java和C++的区别

  • java面向对象,c++为了兼容c,面向对象也面向过程
  • java通过JVM实现跨平台,C++依赖特定的环境
  • java没有指针,有引用,C++有指针
  • java支持垃圾自动回收,C++手动回收
  • java不支持多继承,只能通过多个接口来达到相同的目的,而c++支持多重继承。
  • java不支持操作符重载