基础记录

常用的SQL优化方式
redis的几种部署方式
sprigboot帮助我们做了什么事情(如果没有boot,新建一个web需要自己做哪些东西)
具体说一下oauth2

项目的具体架构。

java拦截器

多线程和多进程,如何选择多线程,在并发的情况是选择多线程还是多进程。

tomcat

JAVA

面向对象的好处:

  • 易维护:可读性强,由于继承的存在,及时改变需求,维护的也只是在局部模块。
  • 质量高:重复现有的,在以前的项目的领域中已被测试过的类使系统满足业务需求并具有较高的质量。
  • 效率高:在以前的项目的领域中已被测试过的类使系统满足业务需求并具有较高的质量。
  • 易拓展:由于继承、封装、多态的特性,自然设计出高内聚、低耦合的系统结构,使得系统更灵活、更容易扩展,而且成本较低。

java性能差的原因是,java是半编译语言,最终的执行代码不是可以直接被cpu执行的二进制机械码。

JAVA和C++的区别:

  • 面向对象,封装继承和多态
  • Java不提供指针直接访问内存,程序内存更加安全
  • java类单继承,C++支持多重继承;虽然java的类不可以多继承,但是接口可以多继承。
  • java自动内存管理,C++手动管理。
  • 在 C 语言中,字符串或字符数组最后都会有一个额外的字符‘\0’来表示结束。但是,Java 语言中没有结束符这一概念。
类型 字节 bit
byte 1 8
char 2 16
short 2 16
int 4 32
float 4 32
long 8 64
double 8 64

装箱与拆箱

装:将基本类型转化为包装器类型。

拆:自动将包装器类型转换为基本数据类型。

OOP

  • 封装:将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过类提供的方法来实现内部信息的操作和访问。

    访问控制符:

    • private:只允许当前类内部访问。
    • package:当前包下的其他类访问。
    • protected:当前包下的其他类访问,子类访问。
    • public:所有类访问。
  • 继承:extends,子类拓展了父类,获得父类的全部成员变量和方法。只能单继承,只有一个直接父类,但可以有无线个间接父类,没有显示指定,继承java.lang.bject

    • 重写父类方法

      static静态方法不能被重写。

      遵循“两同两小一大”规则:方法名相同,形参列表相同;“两小”是指子类方法返回值类型和抛出异常类型比父类方法更小或者更小;一大是子类的方法的访问权限比父类更大或者相等。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      class B {
      public void show() {
      System.out.println("B");
      }
      }

      public class A extends B{
      @Override
      public void show() {
      System.out.println("A"); //重写父类方法
      }
      }

      重载(overload)和重写(Override)的区别:

      • 重载指同一类中多个同名方法根据不同的参数执行不同的逻辑。

      • 重写只子类和父类的同名方法。但是内部逻辑是不一样的。

    • super关键字:访问父类的构造函数,成员方法。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      class B {
      private int x;

      public B(int x) {
      this.x = x;
      }

      public void show() {
      System.out.println("x:" + x);
      }
      }

      public class A extends B{
      private int x;

      public A(int x, int x1) {
      super(x1);
      this.x = x;
      }

      @Override
      public void show() {
      super.show(); //调用被覆盖的父类方法
      }

      public static void main(String[] args) {
      A a = new A(1, 2);
      a.show(); //x:2
      }
      }

    • 父类构造器:子类继承了父类,在初始化子类时,先初始化父类,调用super(),使用super必须放在子类构造器的第一行,而this调用同一个类中重载的构造器也要放在第一行,所以super和this不能同时出现。

  • 多态:相同类型的变量调用同一个方法时呈现出多种不同的特征。

    Java 允许把一个子类对象直接赋给一个父类引用变量,无须任何类型转换。当把一个子类对象赋给父类引用变量时,会出现编译类型和运行类型不一致的情况,此时调用子类和父类的同名方法时(这里的同名指的是子类重写了父类方法),总是表现出子类方法的行为特征。例如:B b = new A() 编译类型看左边,运行类型看右边,因此编译类型为 B,运行类型为 A,当 b 调用 A 和 B 的同名的方法时,运行的总是 A 中的方法。

序列化

程序在运行的时候会产生很多对象,而对象信息也只是在程序运行的时候才在内存中保持其状态,一旦程序停止,内存释放,对象也就不存在了。怎么能让对象永久的保存下来呢?对象序列化。序列化的两个类ObjectOutputStream 和 ObjectInputStream。

  • ProtoBuffer优点:
    • Protobuf 更小、更快、也更简单
    • “向后”兼容性好
    • Protobuf 语义更清晰
    • Protobuf 的编程模式比较友好
  • 缺点:由于文本并不适合用来描述数据结构,所以 Protobuf 也不适合用来对基于文本的标记文档(如 HTML)建模。另外,由于 XML 具有某种程度上的自解释性,它可以被人直接读取编辑,在这一点上 Protobuf 不行,它以二进制的方式存储,除非你有 .proto 定义,否则你没法直接读出 Protobuf 的任何内容。

对于不想进行序列化的变量,使用 transient 关键字修饰。

反射

反射的应用场景

业务代码中使用反射比较少,但是有用,像spring/springboot,mybatis等框架都大量使用了反射机制。

这些框架中大量使用了动态代理,动态代理也是依赖反射。通过反射可以获取任意一个类的所有属性和方法,可以调用这些属性和方法。

注解中也是使用了反射。

优缺点:

  • 优点:代码灵活,为各种框架提供开箱即用的功能提供了便利。
  • 缺点:让我们在运行时有了分析操作类的能力,这同样也增加了安全问题。比如可以无视泛型参数的安全检查(泛型参数的安全检查发生在编译时)。另外,反射的性能也要稍差点。

反射实战

运算符

右左结合:单目,条件,赋值

基本的优先级:

  • 指针最先,单目高于双目
  • 先乘除后加减
  • 先算数,再移位,再位运算。
  • 逻辑最后

异常

Error和Exception,继承自Throwable

两者不同:

Exception:

  • 可以是checked或者unchecked
  • 程序员导致的错误
  • 程序级别处理

Error:

  • 不可控制的unckecked
  • 系统错误或底层资源错误
  • 系统级别捕捉

异常分类:

  • checked exception
  • unckecked exception

修饰符

访问修饰符:private,public,,,,,,,,

非访问修饰符:以下。

static

  • 静态变量:独立于对象的静态变量,无论类实例化多少对象,静态变量只有一份拷贝,也成为类变量,局部变量不能声明为static
  • 静态方法:独立于对象的静态方法,静态方法不能使用类的非静态变量,静态方法从参数列表得到数据,然后计算数据。

final

  • final变量:一旦赋值,不改变,必须显式指定初始值,一般和static一起来创建类常量。

  • final方法:可以被子类继承,但是不能重写。防止方法被篡改。

  • final类:不能被继承。

abstract

  • 抽象类:不能实例化对象,唯一目的就是防止将来对该类进行扩充。不能同时被final和ststic修饰,如果包含抽象方法,必须声明成抽象类,否则出现编译错误。
  • 抽象方法:抽象方法是一种没有任何实现的方法,该方法的的具体实现由子类提供。

拦截器

数据库

  • ACID
    • 原子性:一个事务中的操作,要么全部成功,要么全部失败,如果失败,就回滚到事务开始前的状态。
    • 一致性:从一个一致性状态变换到另一个一致性状态。AB转账,总金额不变。
    • 隔离性:多个用户并发访问数据库,操作同一张表,每个用户开启事务,事务之间互不干扰,事务之间的仓发是隔离的。
    • 持久性:事务一旦提交,数据库中的数据改变就是永久性的。
  • 四种隔离级别
    • 读未提交(Read uncommitted):select不加锁,可能读到‘脏数据’,这是并发最高,一致性最差的隔离级别。
    • 读已提交(Read committed):避免‘脏数据’。
    • 可重复读(Repeattable read):默认隔离级别,避免脏读,不可重复读。
    • 串行化(Serializable):可避免脏读,不可重复读,幻读的发生。一致性最好,性能最差,一般不使用串行化和read uncommitted。
  • #和$符号的区别
    • #将传入的数据当成一个字符串,会自动加双引号。
    • #防止SQL注入
    • $会直接显示生成在SQL中

面试问题记录

1.linux定位cpu占用率高问题

  • top命令查到最占cpu的进程 22686

  • pstack跟踪进程栈 pstack 22686

    该命令可以显示每个进程的栈追踪,如果发现一个服务一直处于work状态,在一段时间内,多次执行pstack,发现代码栈总是停在同一个位置,则需要重点关注。很有可能出了问题。

  • 使用top -H -p 22688查看进程中最占用资源的线程,查到是22970。

  • 使用线程的pid反查其对应的线程号。

  • pstack 22680|grep 22970—>是thread10。

  • 然后使用vim查看进程快照,定位到具体的线程,并查看其调用堆栈。

2.java1.8默认的垃圾收集器

新生代的parallel scavenge(复制)+parallel old(标记整理)

3.底层网络模型

参考链接

4.java内存泄漏

内存溢出:申请了10个字节的空间,但是在这个空间写入11或者以上的字节,出现溢出。

内存泄漏:new申请内存,但是很久不用,但是因为一直被某些实例持有导致GC不能回收,就是应该释放的对象没有被释放。

5.见过哪些弱引用和虚引用

6.设计一个文件格式,要考虑哪些问题

操作系统中的文件系统。

7.列存储

在这篇笔记里

8.Mysql复制问题

在这里

9.著名的topK问题

  • 排序
  • 局部排序,比如用冒泡或者选择
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

请我喝杯咖啡吧~

支付宝
微信