错题集+面试题

什么是软件工程

软件工程是一门研究用工程化方法构建和维护有效、实用和高质量的软件的学科。

什么是数据结构?

数据结构是一种具有一定逻辑关系,在计算机中应用某种存储结构,并且封装了相应操作的数据元素的集合。它包含三方面的内容,逻辑关系、存储关系以及操作。
程序 = 数据结构 + 算法 。

什么是对象 ?

对象就是一个真实世界中的实体,对象与实体是一一对应关系的,意思就是现实世界的每一个实体都是一个对象,所以对象是一个具体的概念。
类是对象的集合,对象是类的实例;

Java语言最基本单位就是类,类似于类型。
类是一类事物的抽象。
可以理解为模板或者设计图纸。

对象

每个对象具有三个特点:对象的状态,对象的行为和对象的标识。

  • 对象的状态用来描述对象的基本特征。
  • 对象的行为用来描述对象的功能。
  • 对象的标识是指对象在内存中都有一个唯一的地址值用来和其他对象区分开来。
  • 类是一类事物的抽象,对象是具体的实现。

4 封装

封装是隐藏对象的属性和实现细节,仅仅对外提供公共的访问方式,比如类和方法
好处:

提高安全性
提高重用性

private关键字
是一个权限修饰符 ,可以用来修饰成员变量和成员方法.被私有化的成员只能在本类中访问

继承

1.概念
  • 继承是面向对象最显著的一个特征
  • 继承是从已有的类中派生出新的类,新类能吸收已有类的数据属性和行为,并扩展新的能力.
  • Java继承是会用已存在的类的定义作为基础建立新类的技术
  • 新类的定义可以增加新的数据或者新的功能,也可以使用父类的功能,但不能选择性的继承父类(超类/基类)
  • 这种继承使得复用以前的代码非常容易,能够大大的缩短开发的周期,降低开发费用.
2.特点
  • 使用extends关键字来表示继承关系
  • 相当于子类把父类的功能复制了一份
  • Java只支持单继承
  • 继承可以传递(爷爷/儿子/孙子这样的关系)
  • 父类的私有成员也会被继承,但由于私有限制访问,所以子类不能使用父类的私有资源
  • 继承多用于功能的修改,子类可以在拥有父类功能的同时,进行功能拓展
  • 像是is a的关系

方法重写Override

  1. 继承以后,子类就拥有了父类的功能
  2. 在子类中,可以添加子类特有的功能,也可以修改父类的原有功能
  3. 子类中方法的签名与父类完全一样时,会发生覆盖/复写的现象
  4. 注意: 父类的私有方法不能被重写
  5. 重写的要求:两同两小一大
  6. 两同:方法名 参数列表 要完全一致
  7. 两小:
    子类返回值类型<=父类的返回值类型(注意此处说的是继承关系,不是值大小)
    子类抛出异常<=等于父类方法抛出异常
  8. 一大: 子类方法的修饰符权限要>=父类被重写方法的修饰符权限

重载Overload 与重写Override的区别

  • 重载:在一个类中的现象:同一个类中,存在方法名相同,参数列表不同的方法
  • 重写:是指建立了继承关系以后,子类对父类的方法不满意,可以重写,遵循两同两小一大原则
  • 重载的意义:是为了外界调用方法时方便,不管传入什么样的参数,都可以匹配到对应的同名方法
  • 重写的意义:在不修改源码的情况下,进行功能的修改与拓展(OCP原则:面向修改关闭,面向拓展开放)

多态

特点:

继承+重写
父类引用指向子类对象
多态中,编译看左边,运行看右边

-不能使用子类的没有重写特有功能

前提:多态对象把自己看做是父类类型
成员变量: 使用的是父类的
成员方法: 由于存在重写现象,所以使用的是子类的
静态成员: 随着类的加载而加载,谁调用就返回谁的

好处:

  • 多态可以让我们不用关心某个对象到底具体是什么类型,就可以使用该对象的某些方法
  • 提高了程序的可扩展性和可维护性

为什么使用多态:
- 为了把所有的子类统一标准,向父类看齐,父类定义的方法多态对象才能用

向上转型和向下转型

  1. 父类引用指向子类对象,而子类引用不能指向父类对象。

  2. 把子类对象直接赋给父类引用叫upcasting向上转型,向上转型不用强制转换吗,如:
    Father f1 = new Son();

  3. 把指向子类对象的父类引用赋给子类引用叫向下转型(downcasting),要强制转换,如:
    f1 就是一个指向子类对象的父类引用。把f1赋给子类引用 s1 即 Son s1 = (Son)f1;
    其中 f1 前面的(Son)必须加上,进行强制转换。

抽象类

  • abstract 可以修饰方法或者类
  • 抽象类中可以没有抽象方法,也可以全抽、半抽、全普
  • 如果一个类包含抽象方法,那么该类必须是抽象类。
  • 子类继承了抽象类以后,要么还是一个抽象类,要么就把父类的所有抽象方法都重写
  • 在 Java 中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
  • 抽象类不可以被实例化
  • 抽象类可以有构造方法,抽象类中的构造函数通常在子类对象实例化时使用
  • 多用于多态中
总结:abstract注意事项
  • 抽象方法要求子类继承后必须重写。
  • 那么,abstract关键字不可以和哪些关键字一起使用呢?以下关键字,在抽象类中。用是可以用的,只是没有意义了。
    1.private:被私有化后,子类无法重写,与abstract相违背。
    2.final:被final修饰后,无法重写,与abstract相违背
    3.static:静态优先于对象存在,存在加载顺序问题。但可以与单独的静态方法!

接口

- 特点
  1. 通过interface关键字来定义接口
  2. 通过implements让子类来实现接口
  3. 接口中的方法全部都是抽象方法(JAVA8)
  4. 可以把接口理解成一个特殊的抽象类(但接口不是类!!!)
  5. 类描述的是一类事物的属性和方法,接口则是包含实现类要实现的方法
  6. 接口突破了java单继承的局限性
  7. 接口和类之间可以多实现,接口与接口之间可以多继承
  8. 接口是对外暴露的规则,是一套开发规范
  9. 接口提高了程序的功能拓展,降低了耦合性
  10. 接口里是没有构造方法的 :如果一个类没有明确指定它的父类,那么它默认继承顶级父类Object,调用的super()是Object的无参构造
  11. 接口里没有成员变量,都是常量。所以,你定义一个变量没有写修饰符时,默认会加上:public static final
  12. 接口里的方法,默认都是抽象的,方法上会默认拼接public abstract。例如:public abstract void save();

抽象类和接口的区别

  1. 抽象类要被子类继承,接口要被类实现。
  2. 接口只能做方法声明,抽象类中可以作方法声明,也可以做方法实现。
  3. 接口里定义的变量只能是公共的静态的常量(public staic final),抽象类中的变量是普通变量。
  4. 接口是设计的结果,抽象类是重构的结果。
  5. 抽象类和接口都是用来抽象具体对象的,但是接口的抽象级别最高。
  6. 抽象类可以有具体的方法和属性,接口只能有抽象方法和不可变常量。
  7. 抽象类有构造方法而接口没有构造方法
  8. 抽象类和接口都不能实例化(创建对象)
  9. 接口会为方法自动拼接public abstract,还会为变量自动拼接public final static

抽象类和接口的应用场景

  • 如果拥有一些方法并且想让它们中的一些有默认实现,那么使用抽象类吧
  • 如果想实现多重继承,那么必须使用接口。由于Java不支持多继承,即一个类只能有一个超类。但是,可以实现多个接口,因此可以使用接口来解决它。
  • 如果基本功能在不断改变,那么就需要使用抽象类,达到解耦目的。如果不断改变基本功能并且使用接口,那么就需要改变所有实现了该接口的类。

this与super的区别

  1. this代表的是本类对象的引用;super代表的是父类对象的引用;
  2. 当本类的成员变量与局部变量同名时,需要使用this.变量名指定本类的成员变量
  3. 当本类的成员变量与父类的成员变量同名时,需要使用super.变量名指定父类的成员变量
  4. this可以实现调用本类构造方法的功能,不能互相调用,需要写在构造方法首行
    this();表示调用本类的无参构造 / this(参数);表示调用本类的对应参数的构造
  5. super也可以实现调用父类构造方法的功能
    super();表示调用父类的无参构造 super(参数);表示调用父类的对应参数的构造
  • 注意:super的使用前提是继承,没有父子类关系,就没有super
  • 注意:this调用构造方法或者super调用构造方法,都必须出现在构造方法的第一行
  • 注意:如果父类没有无参构造,需要手动在子类构造方法的第一行调用其他的含参构造
    拓展:如 的方法以后,可以使用super.方法名(参数列表)来调用

static的特点

  1. 概念

    是java中的一个关键字
    用于修饰成员(成员变量和成员方法)

  2. 特点

    1. static可以修饰成员变量和方法
    2. 被static修饰的资源称为静态资源
    3. 静态资源随着类的加载而加载,最先加载,优先于对象进行加载
    4. 静态资源可以通过类名直接调用,也被称作类资源
    5. 静态被全局所有对象共享,值只有一份
    6. 静态资源只能调用静态资源
    7. 静态区域内不允许使用this与super关键字
  3. 静态变量和实例变量的区别

    • 在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。
    • 在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用

final

1.java.lang包(列举所有final类)

  • 包装类:Boolean,Character,Short,Integer,Long,Float,Double,Byte,Void

  • 字符串类:String,StringBuilder,StringBuffer

  • 系统类:Class,System,RuntimePermission,Compiler

  • 数学类:Math,StrictMath

  • final类不能被继承,没有子类,final类中的方法默认是final的。

  • final方法不能被子类的方法覆盖,但可以被继承,和重载。

  • final成员变量表示常量,只能被赋值一次,赋值后值不再改变。

  • final不能用于修饰构造方法。

注意:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。
boolean类型不能和任何类型进行转换,会报出类型异常错误。

集合

在这里插入图片描述
在这里插入图片描述

//4.map集合的迭代方式一
        /**方式一:
         * 遍历map中的数据,但是map本身没有迭代器,所以需要先转换成set集合
         * Set<Key>:把map中的所有Key值成存入到Set集合当中——keySet()*/
        //4.1将map集合中的key值取出存入set集合中,集合的泛型结束key的类型Integer
        Set<Integer> keySet = map.keySet();
        //4.2想要遍历集合就需要获取集合的迭代器
        Iterator<Integer> it = keySet.iterator();
        //4.3循环迭代集合中的所有元素
        while(it.hasNext()){
            Integer key = it.next();//拿到本轮循环中获取到底map的key
            String value = map.get(key);
            System.out.println(key+" "+map.get(key));
        }
        System.out.println("*************************");
        /**方式二:
         * 遍历map集合,需要把map集合先转成set集合
         * 是把map中的一对键值对key&value作为一个Entry<K,V>整体放入Set
         * 一对K,V就是一个Entry*/
        Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
        Iterator<Map.Entry<Integer, String>> iterator = entrySet.iterator();
        while(iterator.hasNext()){
            Map.Entry<Integer, String> entry = iterator.next();
            System.out.println(entry.getKey()+entry.getValue());

        }
  1. 集合和数组的区别:

    (1)数组长度的是固定的,集合的长度是可变的。

    (2)数组中存储的都是同一类型的元素。集合存储的都是对象,对象的类型可以不一致。

    Java集合类主要由两个根接口Collection和Map派生出来的。Collection有三个子接口: List、Set、Queue(Java5新增的队列)。Java集合大致也可分成List、Set、Queue、Map四种接口体系,注意:Map不是Collection的子接口。
    Map接口:双列数据,保存具有映射关系“key-value对”

  2. HashMap的存储过程:

    • HashMap的结构是数组+链表 或者 数组+红黑树 的形式
    • HashMap底层的Entry[ ]数组,初始容量为16,加载因子是0.75f,扩容按约为2倍扩容
    • 当存放数据时,会根据hash(key)%n算法来计算数据的存放位置,n就是数组的长度,其实也就是集合的容量
    • 当计算到的位置之前没有存过数据的时候,会直接存放数据
    • 当计算的位置,有数据时,会发生hash冲突/hash碰撞
    • 解决的办法就是采用链表的结构,在数组中指定位置处以后元素之后插入新的元素
    • 也就是说数组中的元素都是最早加入的节点
    • 如果链表的长度>8时,链表会转为红黑树,当链表的长度<6时,会重新恢复成链表
  3. Iterator和ListIterator之间有什么区别?
    一.相同点
    都是迭代器,当需要对集合中元素进行遍历不需要干涉其遍历过程时,这两种迭代器都可以使用。
    二.不同点

    • 使用范围不同,Iterator可以应用于所有的集合,Set、List和Map和这些集合的子类型。而ListIterator只能用于List及其子类型。
    • ListIterator有add方法,可以向List中添加对象,而Iterator不能。
    • ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator不可以。
    • ListIterator可以定位当前索引的位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
    • 都可实现删除操作,但是ListIterator可以实现对象的修改,set()方法可以实现。Iterator仅能遍历,不能修改。

集合的详细知识点

集合相关的面试题

集合面试

进程与线程

进程

概念:进程就是正在运行的程序,它会占用对应的内存区域,由CPU进行执行与计算。

进程的特点

  • 独立性
    进程是系统中独立存在的实体,它可以拥有自己独立的资源,每个进程都拥有自己私有的地址空间,在没有经过进程本身允许的情况下,一个用户进程不可以直接访问其他进程的地址空间
  • 动态性
    进程与程序的区别在于,程序只是一个静态的指令集合,而进程是一个正在系统中活动的指令集合,程序加入了时间的概念以后,称为进程,具有自己的生命周期和各种不同的状态,这些概念都是程序所不具备的.
  • 并发性
    多个进程可以在单个处理器CPU上并发执行,多个进程之间不会互相影响.
线程
  1. 线程的概念
    线程是操作系统OS能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位.
    一个进程可以开启多个线程,其中有一个主线程来调用本进程中的其他线程。
    我们看到的进程的切换,切换的也是不同进程的主线程
    多线程可以让同一个进程同时并发处理多个任务,相当于扩展了进程的功能。

  2. 进程与线程的关系
    一个操作系统中可以有多个进程,一个进程中可以包含一个线程(单线程程序),也可以包含多个线程(多线程程序)

  3. 串行与并行

      串行是指同一时刻一个CPU只能处理一件事,类似于单车道
      并行是指同一时刻多个CPU可以处理多件事,类似于多车道
    
  4. 线程生命周期,主要有五种状态:

  • 新建状态(New) : 当线程对象创建后就进入了新建状态.如:Thread t = new MyThread();

  • 就绪状态(Runnable):当调用线程对象的start()方法,线程即为进入就绪状态.
    处于就绪(可运行)状态的线程,只是说明线程已经做好准备,随时等待CPU调度执行,并不是执行了t.start()此线程立即就会执行

  • 运行状态(Running):当CPU调度了处于就绪状态的线程时,此线程才是真正的执行,即进入到运行状态
    就绪状态是进入运行状态的唯一入口,也就是线程想要进入运行状态状态执行,先得处于就绪状态

  • 阻塞状态(Blocked):处于运状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入就绪状态才有机会被CPU选中再次执行.

    根据阻塞状态产生的原因不同,阻塞状态又可以细分成三种:
    
    等待阻塞:运行状态中的线程执行wait()方法,本线程进入到等待阻塞状态
    同步阻塞:线程在获取synchronized同步锁失败(因为锁被其他线程占用),它会进入同步阻塞状态
    其他阻塞:调用线程的sleep()或者join()或发出了I/O请求时,线程会进入到阻塞状态.当sleep()状态超时.join()等待线程终止或者超时或者I/O处理完毕时线程重新转入就绪状态
    
  • 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期

     就绪 → 执行:为就绪线程分配CPU即可变为执行状态"
     执行 → 就绪:正在执行的线程由于时间片用完被剥夺CPU暂停执行,就变为就绪状态
     执行 → 阻塞:由于发生某事件,使正在执行的线程受阻,无法执行,则由执行变为阻塞
    (例如线程正在访问临界资源,而资源正在被其他线程访问)
     反之,如果获得了之前需要的资源,则由阻塞变为就绪状态,等待分配CPU再次执行
    
  1. java实现多线程的方法:继承Thread类,实现runnable接口,实现Callable接口
  • 优缺点:
    1)、继承Thread类为单继承,实现Runnable方法为多实现,所以在灵活性上来说,使用实现Runnable方法更灵活;
    2)、通过实现Runnable接口的方式可以实现多线程内的资源共享;
    3)、增加代码的健壮性,代码可以被多个线程共享,代码和数据独立;
    4)、线程池只能放实现Runnable或callable类的线程,不能直接放入继承Thread类的线程;
    第一二种方式比较:避免了单继承的局限性。
      两种方式的线程代码存放位置不同:
       继承Thread的线程代码放在Thread的子类run的方法中。
       实现Runnable,线程代码存在接口的子类的run方法中。
  1. :线程同步
    线程同步主要使用synchronized关键字;具体有两种实现方式:1、作为关键字修饰类中一个方法;2、修饰方法中的一块区域(代码);

线程池介绍及创建线程池的4种方式

java多线程面试题整理

一:逻辑删除
逻辑删除的本质是修改操作,所谓的逻辑删除其实并不是真正的删除,而是在表中将对应的是否删除标识(is_delete)或者说是状态字段(status)做修改操作。比如0是未删除,1是删除。在逻辑上数据是被删除的,但数据本身依然存在库中。
对应的SQL语句:update 表名 set is_delete = 1 where id = 1;语句表示,在该表中将id为1的信息进行逻辑删除,那么客户端进行查询id为1的信息,服务器就不会提供信息。倘若想继续为客户端提供该信息,可将 is_delete 更改为 0 。

二:物理删除
物理删除就是真正的从数据库中做删除操作了。
对应的SQL语句:delete from 表名 where 条件;执行该语句,即为将数据库中该信息进行彻底删除,无法恢复。

Java中的String,StringBuilder,StringBuffer三者的区别

1.在这方面运行速度快慢为:StringBuilder > StringBuffer > String

  • String最慢的原因:String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。
  • 在String拼接时,JVM就会,不断的创建、回收对象来进行这个操作了

2.在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的

  • 如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。

3.总结一下
  String:适用于少量的字符串操作的情况
  StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
  StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况

Spring的知识点

Spring MVC 和 Spring 总结
Spring常用的三种依赖注入方式

jvm垃圾回收的流程及垃圾回收器详解

浅谈数据库集群(一)

Linux常用命令(面试题)

Mybatis中$与#的区别

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值