java面试题

目录

java基础

java语言的优点

变量的分类

属性(成员变量)和局部变量的区别?

 数组的特点:

面向对象的主要内容

面向对象的两个要素

方法重载和方法重写 

面向对象的三大特性?

四种权限修饰符

==和equals的区别?

hashcode()和equals()的比较

final 在 java 中有什么作用?

final、finally和finalize

抽象类与接口有哪些异同?

throw和throws的异同

sleep和wait的区别

join和yield的区别

 集合

list和set的区别?

ArrayList、LinkedList、Vector的异同?

数组和集合有什么区别?

进程和线程

请你说说你对多线程的理解?

创建多线程有哪些方式?

线程的生命周期?线程有哪些状态?

对线程安全的理解?

说说你对守护线程的理解?

为什么要使用线程池?线程池的主要参数?

线程池的处理流程?

 线程池中阻塞队列的作用?为什么是先加入队列而不是先创建线程?

线程池中线程复用的原理?

线程间的通讯方式?

并发的三大特性?

如何理解volatile关键字?

ReentrantLock的公平锁和非公平锁的底层实现?

ReentranLock中lock和trylock的区别?

Sychronized的偏向锁、轻量级锁、重量级锁?

Sychronized和ReentranLock的区别?

死锁问题

 MySQL的基本问题

索引的基本原理?

索引是什么?为什么要使用索引?

索引的分类

MYISAM和InnoDB的区别?

hash索引和B+Tree索引的区别?

B+Tree和B-Tree的区别?

索引设计的原则?

关于数据库事务的理解?

关于事务的ACID特性

什么是脏读、不可重复读、幻读?

什么是事务的隔离级别?MySQL的默认隔离级别是什么?

ACID是靠什么来保证的?

谈一谈你对MySQL锁的理解?

MySQL锁的分类

行级锁、表级锁、页级锁的理解?

谈谈你对读写锁的理解?

MySQL中InnoDB引擎的行锁是怎么实现的?

数据库的悲观锁和乐观锁是什么?怎么实现的?

什么是死锁?怎么解决?

什么是主从复制?

主从数据库的作用?

主从复制的原理

undolog和redolog的区别?

关于MySQL的查询语句的调优?

MySQL的三大范式

left join和right join的区别?

redis的基本认识

​编辑 Redis的持久化机制?

redis过期键的删除策略?

redis的失效策略?

Redis的线程模型?以及单线程快的原因?

 缓存雪崩、缓存击穿、缓存穿透?

 简述Redis事务的实现


java基础

java语言的优点

1.java是纯面向对象的语言,开发人员更易理解,编写程序更简单

2.java是跨平台性的语言,可以一处编译,处处运行,因此具有可移植性很好

3.java提供了很多的内置类库,简化了开发人员的程序设计工作,缩短了项目的开发时间。

4.提供了对web应用开发的支持

5.具有较好的安全性和健壮性

6.去除了C++语言中难以理解,容易混淆的特性,使程序更加严谨整洁。

变量的分类

一、变量的分类--按照声明位置不同

  • 在方法体外,类体内声明的变量称为成员变量

  • 在方法体内部声明的变量称为局部变量

属性(成员变量)和局部变量的区别?

相同点:

  • 1.定义变量的格式:数据类型 变量名 = 变量值
  • 2.先声明,后使用
  • 3.变量都有其对应的作用域

不同点:

在类中声明的位置不同

  • 1.属性:直接定义在类的一对{}内
  • 2.局部变量:声明在方法内、方法形参、构造器形参、构造器内部的变量

关于权限修饰符的不同 ​

  • 1.属性:可以在声明属性时,指明其权限,使用权限修饰符。 /*常用的权限修饰符:private、public、缺省、protected*/
  • 2.局部变量:不可以使用权限修饰符 ​

默认初始化值的情况不同:

  • 1.属性:类的属性,根据其类型,都有默认初始化值。

整型(byte、short、int、long):0

浮点型(float、double):0.0

字符型(char):0(或‘\u0000’)

布尔型(boolean):false

引用数据类型(类、数组、接口):null ​

  • 2.局部变量:没有默认初始化值

在内存中加载的位置不同:

  • ​ 1.属性:加载到堆空间中(非static)
  • ​ 2.局部变量:加载到栈空间

二、变量的分类--按数据类型分类

Java是强类型语言,对于每一种数据都定义了明确的具体数据类型(强类型语言),在内存中分配了不同大小的内存空间。

 数组的特点:

数组(Array),是多个相同类型数据按一定顺序排列的集合。

数组的特点:

  • 1)数组属于引用类型的变量。数组的元素,既可以是基本数据类型,也可以是引用数据类型。

  • 2)创建数组对象会在内存中开辟一整块连续的空间;

  • 3)数组的长度一旦确定,就不能修改;

  • 4)数组是有序排列的。

面向对象的主要内容

1.Java 类及类的成员:属性、方法、构造器、代码块、内部类

2.面向对象的三大特征:封装、继承、多态性、(抽象性)

3.其它关键字:this、super、static、final、abstract、interface、package、import 等

面向对象的两个要素 ==>类和对象

1.类:对一类事物的描述,是抽象的、概念上的定义

2.对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)。

可以理解为:类= 抽象概念的人;对象= 实实在在的某个人

方法重载和方法重写

1.方法重载:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。

“两同一不同”:

同一个类 相同方法名 参数列表不同(参数列表:参数个数和参数类型)

2.方法重写:子类继承父类以后,可以对父类中的方法进行扩展、覆盖操作。

约定俗称:子类中的叫重写的方法,父类中的叫被重写的方法。

① 子类重写的方法的方法名和形参列表必须和父类被重写的方法的方法名、形参列表相同;

② 子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限,

特殊情况: 子类不能重写父类中声明为private权限的方法;

③ 返回值类型:

父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void;

父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类;

父类被重写的方法的返回值类型如果是基本数据类型(比如:double),则子类重写的方法的返回值类型必须是相同的基本数据类型(必须是:double)。

④ 子类方法抛出的异常不能大于父类被重写的方法抛出的异常;

注意:

子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为static的(不是重写)。

法重载与方法重写的区别?

答:方法的重写和重载是Java多态性的不同表现。

1.重写是父类与子类之间多态性的一种表现,重载是一个类中多态性的一种表现。

如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了。

如果在一个类中定义了多个同名的方法,它们或有不同的参数列表,则称为方法的重载(Overloading)。

面向对象的三大特性?

封装:

我们的程序追求高内聚,低耦合

高内聚:类的内部数据操作细节自己完成,不允许外部干涉; 低耦合:仅对外暴露少量的方法用于使用。

隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。

继承:

为什么要有继承?==>继承性的好处

  • ① 减少了代码的冗余,提高了代码的复用性;

  • ② 便于功能的扩展;

  • ③ 为之后多态性的使用,提供了前提

体现:

1.一旦子类 A 继承父类以后,子类 A 中就获取了父类 B 中声明的所有属性和方法

特别的,父类中声明为 private 的属性或方法,子类继承父类以后,仍然可以获取父类中私有的结构。只是因为封装性的影响,使得子类不能直接调用父类的结构而已。

2.子类继承父类以后,还可以声明自己特有的属性或方法,实现功能的拓展。

注意:

如果我们没有显式的声明一个类的父类的话,则此类继承于 java.lang.Object 类
​
所有的 java 类(除 java.long.Object 类之外)都直接或间接地继承于 java.lang.Object 类;
​
意味着,所有的 java 类具有 java.lang.Object 类声明的功能。

多态:

1.多态性:一个事务的多种形态

2.对象的多态性:父类的引用指向子类的对象 Person p = new Man();

3.多态的使用:虚拟方法调用

虚拟方法指的是父类方法

虚拟方法调用:当调用与父类同名同参数的方法时,实际调用的是子类重写父类的方法

4.总结:

有了对象的多态性之后,我们在编译期,只能调用父类中的方法,但在运行期,我们实际执行的是子类重写父类的方法。 即:Person p = new Man(); 编译看左边,执行看右边

多态性的使用前提:①类的继承关系(存在子父类)②方法的重写

四种权限修饰符

对于 class 的权限修饰只可以用 public 和 default(缺省)。

  • 被public 修饰的类,可以在任意地方被访问。

  • 被default 修饰的类,只可以被同一个包内部的类访问。

==和equals的区别?

1.==:运算符

①可以使用在基本数据类型和引用数据类型中

如果使用在基本数据类型中,比较两个变量保存的数据是否相等(数据类型不一定要相同)

如果使用在引用数据类型中,比较两个对象的地址值是否相同,即两个引用是否指向同一个对象

2.equals():方法

①是一个方法,且只能用于引用数据类型

②Object类中equals()的定义:

则可看出在java.lang.Object下equals()的定义和==的作用是相同的

③String、Date、File、包装类等都重写了Object类中的equals()方法,不是比较两个引用的地址是否相同,而是比较两个对象的“实体内容”是否相同。

hashcode()和equals()的比较

1.hashcode()和equals()都定义在JDK的Object.java中,这就意味着Java中的任何类都包含有他们。

2.hashcode()重写前返回的是对象的地址,而重写后返回的是一个整数;equals()在重写前比较的是对象的地址,而重写后比较的是对象的实体内容。

3.在重写后,如果两个对象比较的equals()相等,那么这两个对象的hashCode()肯定相等,就是说equals()是绝对靠谱的;如果两个对象比较的hashCode()相等,那么equals()去做比较却不一定相等,就是说hashCode()不是绝对可靠的

通过hashcode和equals的搭配使用,可以提高开发效率

在比较对象是否相等时,可以先通过hashcode方法比较,如果结果不想等,则两个对象一定不想等;如果相等,在用equals方法进行比较,这样hashcode方法就可以比较出大部分对象,从而提高效率。

比如:HashSet集合都知道吧,它的特点就是无序,元素唯一,主要靠的就是重写hashCode()和equals()方法

final 在 java 中有什么作用?

用于修饰类、类属性和类方法

1.修饰方法:当使用final修饰方法时,这个方法将成为最终方法,无法被子类重写。但是,该方法仍然可以被继承。

2.修饰类:当用final修饰类时,该类成为最终类,无法被继承。比如常用的String类就是最终类。

3.修饰属性:当用final修饰属性时,该属性为常量不可修改

public static void main(String[] args) {
    final Person p = new Person(20, "炭烧生蚝");
    Person m = p;
    p.setAge(18);   //可以修改p对象的数据
    System.out.println(p.getAge()); //输出18

    Person pp = new Person(30, "蚝生烧炭");
	// p = pp; //这行代码会报错, 不能通过编译, 因为p经final修饰永远指向上面定义的p对象, 不能指向pp对象.
 

final、finally和finalize

①final:最终的 ==>可以用来修饰一个类、方法、变量

final用来修饰一个类,此类将不能被继承,如:String类、System类、StringBuffer类

final用来修饰一个方法,此方法将不能被重写,如:Object类中的getClass()

final用来修饰一个变量,此时的"变量"(成员变量或局部变量)就是一个常量,只能被赋值一次

注意:对于一个 final修饰 变量

如果是基本数据类型的变量,则其数值一旦在初始化后便不能更改;

如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象,但指向的引用变量的内容可以被改。

②finally:一定会被执行

finally块通常放在try、catch的后面。

finally中的语句是正常执行或者处理异常之后必须执行的语句,finally块一般是用来关闭(释放)物理资源(数据库连接,网络连接,磁盘文件等)。无论是否发生异常,资源都必须进行关闭。

是可选的,不一定非要出现==>当没有必要资源需要释放时,可以不用定义finally块

③finalize:方法名 在java.lang.Object类中定义的

finalize是Object类中的一个方法,在垃圾收集器执行的时候会调用被回收对象的finalize()方法,可以覆盖此方法来实现对其他资源的回收,例如关闭文件等。需要注意的是,一旦垃圾回收器准备好释放对象占用的空间,将首先调用其finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。

抽象类与接口有哪些异同?

①接口和抽象类都不能被实例化,但抽象类是有构造器的,而接口不存在构造器

②接口可以被多继承,而java对于类具有单继承性,所以抽象类不能被多继承

③抽象类可以存在普通方法,接口中只存在public abstract方法

④抽象类中的成员变量可以是各种类型的,接口中的成员变量只能是public static final类型的

throw和throws的异同

1.throw是使用在方法体内的,throws是在方法声明上使用的

2.throw后面接的是异常对象,只能接一个,throws后面接的是异常类型,可以接多个

3.throw是在方法中出现不正确情况是,手动来抛出异常,结束方法,执行了throw语句一定会出现异常;而throws是用来声明当前方法有可能会出现的某种异常

sleep和wait的区别

1.相同点:一旦执行方法,都会使当前线程进入阻塞状态

2.不同点:

①两个方法的声明位置不同: sleep()是在Thread类中声明的静态本地方法,wait()是在Object类中声明的本地方法

②调用时需满足的条件不同:sleep()可以在任何被需要的场景下使用,wait()必须在同步代码块或者同步方法中使用(依赖synchronized关键字)。

③如果两个方法都声明在同步代码块或者同步方法中,sleep()不会释放锁,而wait()会释放锁,并且加入等待列

④sleep()用于当前线程休眠,而wait()用于线程间的通信

join和yield的区别

join:Thread的非静态方法,join()让一个线程等待另外一个线程完成才继续执行。如果在线程A中调用B线程的join()方法,则A线程将会被阻塞,直到B线程执行完为止,A才能得以继续执行。

yield:使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间。

 集合

java集合可分为Collection和Map两种体系:

1.Collection:单列数据,定义了存取一组对象的方法的集合

①List:存储有序的、可重复的数据。

ArrayList 、LinkedArrayList 、Vector

ArrayList:是List接口的主要实现类;线程不安全,效率高;底层使用Object[] elementData存储
LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双链表存储
Vector:是List接口的古老实现类;线程安全,效率低;底层使用Object[] elementData存储(不推荐使用)

②Set:存储无序的、不可重复的数据。

HashSet、LinkedHashSet、TreeSet

list和set的区别?

首先list和set都继承于collection接口, ​

①List是有序的,按照对象进入的顺序保存对象;是可重复的,允许多个null元素对象,可以使用Iterator获取所有对象,再逐一遍历,还

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值