Post

Java基础

Java 基础

JDK、JRE、JVM 关系

  • JDK:java 开发工具包
  • JRE:java 运行环境
  • JVM:java 虚拟机

三者关系

Java 数据类型

  1. 基本数据类型(四类八种)
    • 整型(byte、short、int、long)
    • 浮点型(float、double)
    • 字符型(char)
    • 布尔型(boolean)
      四类八种
  2. 引用数据类型
  • 类(class)
  • 接口(interface)
  • 数组

&和&&的区别

  • &和&&都可以用作逻辑与的运算符
  • 表示逻辑与(and)
  • &&还具有短路的功能,即如果第一个表达式为 false,则不再计算第二个表达式

重载(Overload )和重写 (Override )

  1. 重载
    • 发生在一个类中,方法名相同,参数列表不同,方法体不同
    • 编译器在编译时根据方法的签名自动绑定调用的方法
  2. 重写
  • 发生在父子类中,方法名称相同,参数列表相同,方法体不同
  • 重写方法被调用时,看对象的类型
  • 重写遵循”两同两小一大”原则:
    • 两同:
      • 方法名称相同
      • 参数列表相同
    • 两小:
      • 派生类方法的返回值类型小于或等于超类方法的
        • void 时,必须相等
        • 基本类型时,必须相等
        • 引用类型时,小于或等于
      • 派生类方法抛出的异常小于或等于超类方法的
    • 一大:
      • 派生类方法的访问权限大于或等于超类方法的

重写与重载的区别

  • 重写(Override):
    • 发生在父子类中,方法名称相同,参数列表相同,方法体不同
    • 遵循”运行期”绑定,看对象的类型来调用方法
  • 重载(Overload):
    • 发生在一个类中,方法名称相同,参数列表不同,方法体不同
    • 遵循”编译期”绑定,看参数/引用的类型来绑定方法

访问修饰符,作用域

作用域

是否可以继承 String

String 类是 final 类,不可以被继承

抽象类(abstract class)和接口(interface)有什么异同

不同

  • 抽象类中可以有构造器,接口不能定义构造器
  • 抽象类中可以有普通成员变量和常量,接口中只能有常量,而且只能是 public static final 不写默认
  • 抽象类中可以有抽象方法,也可以由普通的方法,接口中只能有抽象的方法而且修饰符只能是 public abstract 不写默认
  • 抽象类只能是单继承,多实现,接口是可以多继承其他接口,但是不能实现接口,和不能继承其他类
  • 抽象类中可以有静态的方法,接口中不可以
  • 抽象类继承 object 而接口不继承

相同

  • 不能够实例化
  • 抽象类接口作为引用类型

静态变量和实例变量区别

  • 静态变量:称为类变量,归类所共有,不依赖某个对象们可以通过类名直接访问
  • 实例变量:必须依存实例,只能通过对象访问到他

面向对象的基本特征

  • 封装:把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口
  • 继承:从已有类得到继承信息创建新类的过程,子类拥有父类一切非私有的属性和方法
  • 多态:指允许不同子类型的对象对同一消息作出不同的响应,同一种事物的不同种表现形式
  • 抽象:将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面

java 中实现多态的机制是什么 重写、重载、父类的声明指向子类的对象

==和 equals 的区别

  • ==:比较基本数据类型是比较数值是否相等,引用数据类型,则比较对象地址是否相等(= =是比较数值和地址相等才相等)
  • equals:比较两者内容是否相等

String、StringBuffer、StringBuilder 的区别

  • String:是不可变的,对 string 的改变都会返回一个新的对象,线程安全的
  • StringBuffer:是可变的,可以对字符串修改,是线程安全的
  • StringBuilder:是可变的,可以对字符串修改,线程不安全的,性能上有所提升

final, finally, finalize 的区别

  • final:是声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承
  • finally:是异常处理语句机构一部分,表示总是执行
  • finalize:是 Object 类的方法,GC 回收执行时候此方法

异常处理

Throwable 异常分类

Error(错误)和 Exception(异常)

  • Error(错误):是程序无法处理的错误
  • Exception(异常):是程序本身可以处理的异常
常见 RuntimeException
  1. java.lang.NullPointerException 空指针异常;
  2. java.lang.ClassNotFoundException 指定的类找不到;
  3. java.lang.NumberFormatException 字符串转换为数字异常;
  4. java.lang.IndexOutOfBoundsException 数组角标越界异常;
  5. java.lang.IllegalArgumentException 方法传递参数错误;
  6. java.lang.ClassCastException 数据类型转换异常;
  7. java.lang.NoClassDefFoundException 未找到类定义错误;
  8. SQLException SQL 异常
  9. java.lang.InstantiationException 实例化异常
  10. java.lang.NoSuchMethodException 方法不存在异常

异常和错误的区别:异常能被程序本身可以处理,错误是无法处理

try、catch、finally

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

线程

创造线程三种方式

  1. 继承 Thread 类创建线程
  2. 实现 Runnable 接口创建线程
  3. 使用 Callable 和 Future 创建线程

线程的状态

graph LR
  A[就绪] --> B[运行]
  B --> D[synchronize阻塞]
  D --> E[wait 和 sleep挂起]
  E --> F[结束]

sleep() 和 wait()的区别

最大的不同是在等待时 wait 会释放锁,而 sleep 一直持有锁。 wait 通常被用于线程间交互, sleep 通常被用于暂停执行

synchronized

是多个线程之间访问资源同步性,修饰的方法代码块在任意时刻只能有一个线程执行

  • 修饰实例方法:实例加锁
  • 修饰静态方法:对象加锁
  • 修饰代码块:

什么是线程池

线程池就是事先将多个线程对象放到一个容器中,当使用的时候就不用 new 线程而是直接去池中拿线程即可,节省了开辟子线程的时间,提高的代码执行效率。

线程池的优点

  • 第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
  • 第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
  • 第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

悲观锁与乐观锁

  • 悲观锁:假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁 ,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。
  • 乐观锁:是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据, 可以使用版本号机制和 CAS 算法实现

IO

  • 方向:输出流(inputStream)和输出流(outputstream)
  • 功能:节点流和处理流
  • 单位:字节流和字符流 字节流 字符流

集合

Collection 和 Collections 的区别

  • Collection:是集合累的上级接口,继承与他的接口主要是 Set 和 List
  • Collections:是正对集合类的帮助类,他提供一系列静态方法实现对各种的搜索、排序、线程安全化操作。

List

  • Collection 的子接口
  • 底层是数组方式实现
  • 有序可重复的
  • 遍历方式:for-each、for、迭代器(Iterator)

  • 实现类

  • ArrayList 底层结构是数组,底层查询快,增删慢
  • LinkedList 底层结构是链表型的,增删快,查询慢
  • voctor 底层结构是数组 线程安全的,增删慢,查询慢

Set

  • Collection 的子接口
  • 底层是散列表方式实现
  • 无序不可重复的
  • 遍历方式:for-each、for、迭代器(Iterator)

  • 实现类

  • HashSet(无序,唯一): 基于 HashMap 实现的,底层采用 HashMap 来保存元素
  • LinkedHashSet: LinkedHashSet 继承与 HashSet,并且其内部是通LinkedHashMap 来实现的。有点类似于我们之前说的LinkedHashMap 其内部是基于 Hashmap 实现一样,不过还是有一点点区别的。
  • TreeSet(有序,唯一): 红黑树(自平衡的排序二叉树。)

Map

  • 键值对方式呈现
  • Map 是有序,key 不重复,value 可重复
  • 遍历方式:for-each、迭代器(Iterator)、通过键值遍历

  • 实现
  • HashMap: JDK1.8之前HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希 冲突而存在的(“拉链法”解决冲突).JDK1.8以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间
  • LinkedHashMap: LinkedHashMap 继承自 HashMap,所以它的底层仍然是基于拉链式散列结构即由数组和 链表或红黑树组成。另外,LinkedHashMap 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以-保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑
  • HashTable: 数组+链表组成的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的
  • TreeMap: 红黑树(自平衡的排序二叉树)

HashMap 和 HashTable 区别

  • HashMap 是非线程安全的,Hashtable 是线程安全的
  • HashMap 要比 Hashtable 性能高一点
  • HashMap 中 key 和 value 都可以可以为 null,HashTable 不可以 put 就会出异常

List、 Set、Map 的区别

  1. List 和 Set 是 Collection 的子接口,map 不是
  2. List 的底层是数组的方式实现, Set 是散列表的方式实现, map 是键值对的方式
  3. list 是有序可重复的, Set 是无序不可重复的, map 是有序, key 不重复, value 可重复
  4. list 和 Set 可直接使用 iterator 来进行遍历, map 只能通过先遍历 Key 在遍历 value.

内部类

定义:指在一个外部类的内部再定义一个类 分类:成员内部类、局部内部类、静态内部类、匿名内部类

匿名部类可以继承其他类或者实现其他接口

作用:

  • 可以实现多重继承
  • 内部类拥有外围类的所有元素访问权限
  • 内部类可以很好实现隐藏

Java 反射

通过方法获取类的字节码,得到字节码之后,通过反射来创建对象,获取私有属性和方法,在 Spring 中就是依赖反射注入的,在 jdbc 中,通过反射生成驱动对象实 获取字节码的方式

  • class.forNam(className)
  • 类名.class
  • this.getClass()
This post is licensed under CC BY 4.0 by the author.