Java基础

1. ==和equals区别

  1. ==:基本数据类型比较值,引用数据类型比较内存地址
  2. equals:基本数据类型没有,引用数据类型如果没有重写,比较值

2. hashcode和equals

  1. hashcode会返回调用对象的hash值,一般与equals一起使用,用于判断两个对象是否相同,比如hashMap就是使用hashcode和equals实现key唯一的特性
  2. 对于两个hashcode相同的对象,他们的equals不一定相同,因为可能存在hash冲突。而两个equals为true的对象,他们的hashcode必须相同,因此重写equals必须重写hashcode

3. 基本数据类型和引用数据类型、值传递和引用传递

  1. 数值类型:int(32位4字节)、byte(8位1字节)、short(16位2字节)、long(64位8字节)、float(32位4字节)、double(64位8字节)
  2. 字符类型:char(16位2字节)
  3. 布尔类型:boolean(1位,0和1表示)
  4. 引用数据类型:对象、包装类、字符串
  5. 如果是基本数据类型,是值传递。如果是引用数据类型,是引用传递

4. Integer对象、缓存池对象、装包拆包

  1. 堆对象:Integer heap = new Integer(123),在堆中创建一个123的Integer对象。
  2. 缓存池对象:Integer cache = 123,在缓存池中查看是否存在123,如果有,指向它,否则创建一个123放入到缓存池,指向它
  3. 装包:Integer.valueOf()
  4. 拆包:Integer.intValue()
  5. int和Integer比较时,将Integer拆包成int
  6. heap == cached,比较内存地址,false
  7. Integer缓存池大小:-128 ~ 127

5. String、StringBuilder、StringBuffer

  1. String是final类,不可变,线程安全,每次拼接都要创建一个新的String对象接收
  2. StringBuilder和StringBuffer有append方法进行拼接
  3. 线程安全:StringBuffer的append方法使用synchronized修饰
  4. 运行速度:StringBuilder、StringBuffer、String
  5. 使用场景
    1. String:操作量少
    2. StringBuffer:多线程数据量大
    3. StringBuilder:单线程数据量大

6. String对象、字符串缓存池对象(对象,存放在JVM的堆中)

  1. 堆对象:String heap = new String("123"),在堆中创建一个"123"的字符串对象
  2. 缓存池对象:String cache = "123",在缓存池中查看是否有"123",有就指向它,否则新建一个存入然后指向它
  3. heap == cache,比较内存地址,false
  4. String str1 = new String("A"+"B")会创建几个对象:5个
    1. 字符串常量池:A、B、AB
    2. 堆:AB
    3. 引用:str1
  5. String str2 = new String("A") + "B"会创建几个对象:3个
    1. 字符串常量池:AB
    2. 堆:AB
    3. 引用:str2

7. static:类、方法、变量、代码块

  1. 修饰类:静态内部类,不能继承,外部类.内部类访问
  2. 修饰方法:静态方法,类.方法名访问,不能访问非静态成员,不能使用this关键字。静态方法随类加载而加载时非静态成员和调用对象还不一定存在
  3. 修饰变量:静态变量,类.变量名访问,类加载时加载,只加载一次,内存中只有一份,修改后的值就是最新值
  4. 修饰代码块:静态代码块,类加载时被执行,只执行一次

8. 静态变量、局部变量、成员变量、类加载顺序

  1. 静态变量随类,类.变量名访问,存放在JVM的方法区
  2. 成员变量随对象,对象.变量名访问,存放在JVM的堆中
  3. 局部变量在方法内定义,存放在JVM的java虚拟机栈或者本地方法栈
  4. 类加载顺序:静态变量、静态代码块、构造函数、非静态变量、非静态代码块

9. final:类、方法、变量

  1. 修饰类:不可继承
  2. 修饰方法:不可重写
  3. 修饰变量:常量,一般与static一起使用,常量必须赋初值,不可修改
  4. 好处:线程安全、常量池可以减少重复常量的创建和销毁

10. super、this

  1. super
    1. 指代当前对象的父类,super.xxx来调用父类的成员
    2. super()调用父类的构造函数
  2. this
    1. 指代当前对象,this.xxx调用当前类的成员
    2. this()调用当前类的构造函数

11. 面向对象的三大特征:封装、继承、多态

  1. 封装:使用private修饰属性,通过getter和setter设置和获取
  2. 继承:子类可以继承父类的非私有成员,但是不能继承父类的构造函数,super()调用父类构造函数。java只支持单继承,子类只能有一个父类
  3. 多态
    1. 前提:继承和实现
    2. 表现:父类引用指向子类对象,接口引用指向实现类对象
    3. 编译时多态:重载,参数数量或参数类型不同,编译时能够确定调用哪一个方法
    4. 运行时多态:重写,只有方法体不同,编译时无法确定,只能在运行时根据指向关系来确定,比如父类引用指向子类对象,调用子类的方法

12. 抽象类

  1. 定义:abstract定义,extends继承,抽象类是内部类时可以使用private修饰,不是内部类则不能使用private修饰
  2. 实现:子类必须重写所有抽象方法
  3. 构造函数:有
  4. 方法:抽象方法的权限范围是public和protected。抽象类可以有普通方法,比如静态方法和非静态方法
  5. 变量:无权限要求,可以有静态变量和成员变量

13. 接口

  1. 定义:interface定义,implements实现,只能使用public修饰
  2. 实现:实现类必须重写所有抽象方法
  3. 构造函数:无
  4. 方法:接口的普通方法默认是抽象方法
  5. 变量:默认是public static final,必须赋初值

14. 接口和抽象类的区别

  1. 抽象类:is-a,定义了被抽象的对象它是什么,比如说鸟类这个物种,它下面其实细分有很多不同的鸟:麻雀、鸽子、鹦鹉
  2. 接口:has-a,定义了对象能做什么,提供了一些规范,比如说动物能做什么动作,规定一些方法比如:睡觉、吃东西、喝水、跑步之类的方法

15. 什么时候用接口什么时候用抽象类

  1. 定义对象的本质时,也就是需要定义它是什么东西的时候,可以使用抽象类
  2. 拓展事物功能时,可以使用接口
  3. 需要实现多继承时使用接口

14. 反射

  1. 含义:对于任何一个类来说,在运行都可以通过反射来获取它的属性和方法,对于任何一个对象来说,都可以通过反射调用它的方法和属性。
  2. 获取class对象的三种方式
    1. User.class,不会初始化
    2. User.getClass().getName(),初始化静态变量
    3. Class.forName(),初始化静态变量和执行静态代码块

15. 异常:Error和Exception都是继承自Throwable

  1. Error是JVM错误,JVM无法处理,比如OOM和SOF
  2. Exception是JVM异常,JVM可以处理,分为受检异常和非受检异常
    1. 受检异常:使用try/catch/finally代码块捕获,比如IO异常
    2. 非受检异常:无法捕获,RuntimeException运行时异常,比如除0异常、数组越界异常、空指针异常,Error也是属于非受检异常,无法预知

16. 设计模式:单例、代理

1. 单例:用于封装工具类,使整个系统数据统一

  1. 特征:唯一实例、私有的构造函数、公有的创建实例方法
  2. 饿汉模式:线程安全,类加载就创建实例,调用创建实例方法直接返回已创建的实例,内存只存在一份,可能会导致内存浪费,不适合创建大对象
    public class Hungry{
     private static Hungry hungry = new Hungry();
     private static Hungry(){};
     public static Hungry getInstance(){
         return hungry;
     }
    }
  3. 懒汉模式:线程不安全,调用创建实例的方法时才会自行创建类实例,多线程下可能会创建多个实例
    public class Lazy{
     private static Lazy lazy = null;
     private static Lazy(){};
     public static Lazy getInstance(){
         if(lazy == null){
             lazy = new Lazy();
         }
         return lazy;
     }
    }
  4. 双重检查:synchronized保证线程安全,volatile保证构造实例的4个指令不重排序,第一次判空防止进入同步块,第二次判空防止创建多个实例
    public class Double{
     /*
     1. 申请空间
     2. 初始化默认值
     3. 执行构造
     4. 连接引用
     */
     private volatile static Double double = null;
     private static Double(){};
     public static Double getInstance(){
         if(double == null){
             synchronized(Double.class){
                 if(double == null){
                     double = new Double();
                 }
             }
         }
         return double;
     }
    }

2. 代理模式

  1. 三个对象
    1. 抽象对象:使用接口或者抽象类定义,定义抽象方法
    2. 代理对象:实现抽象对象,重写抽象方法,提供具体的方法体
    3. 真实对象:实现抽象对象,调用代理对象提供的方法完成抽象方法
  2. 静态代理:手动编写
  3. 动态代理:反射重写
  4. SpringAOP的原理是动态代理
    1. 如果代理对象是实现类,使用jdk动态代理,利用拦截器(必须实现InvocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理
    2. 如果代理对象不是实现类,使用cglib动态代理,ASM框架重写字节码文件,动态生成代理对象的子类,子类重写要代理对象的所有非final的方法
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务