58到家一面面经整理

以下为牛客网精选面试题,网上资料整理解答。

58到家一面

0.日常自我介绍;

1.讲一讲java八大基本数据类型;
Java语言提供了八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。
1、数据类型:
(1)整形数据类型:byte、int、short、long
整形数据类型在java程序中有3种表示形式,分别为十进制、八进制、十六进制
注意:不能以0作为十进制数的开头(0除外),八进制必须以0开头、十六进制必须以0X或者0x开头
byte a =127; //1个字节,8位 -27~27-1
int b = 0x10;//4个字节,32位 -231~231-1 Integer
short c=10;//2个字节,16位 -2^15~ 2^15-1
long d = 10L;//8字节,64位 -263~263-1,在后面加l或L
数据类型 内存空间(8位等于1个字节) 取值范围
bype 8位 -27~27-1
short 16位 -215~215-1
Int 32位 -231~231-1
Long 64位 -263~263-1
(2)浮点数据类型:float、double
Java语言中浮点类型分为单精度浮点类型(float)和双精度浮点类型(double)
float floatA=1.5F;//后面加f或F,不然会识别为double类型
double doubleA = 2.5;//后面可以加d或D,可加,可不加
数据类型 内存空间(8位等于1个字节) 取值范围
float 32位 1.4E-45~ 3.4028235E38
double 64位 4.9E-324~ 1.7976931348623157E308
Float和Double的最小值和最大值都是以科学记数法的形式输出的,结尾的"E+数字"表示E之前的数字要乘以10的多少倍。比如3.14E3就是3.14×1000=3140,3.14E-3就是3.14/1000=0.00314
2、字符型:char
Char类型是一个单一的16位Unicode字符
最小值是’\u0000’(即为0)
最大值是’\uffff’(即为65535);
Char数据类型可以储存任何字符
//Unicode字符集\u0391-\uFFE5 是中文字符集
转义字符:
/*\n 换行(\u000a)
\t 水平制表符(\u0009)
\b 空格 (\u0008)
\r 回车 (\u000d)
\f 换页(\u000c)
’ 单引号(\u0027)
" 双引号(\u0022)
\反斜杠(\u005c) */
3、布尔型:boolean
布尔类型又称为逻辑类型,通过关键字boolean来定义布尔类型变量,只有true和false,分别代表逻辑中的“真”和“假”。布尔值不能与整形类型进行转换。布尔类型通常用在流程控制中作为判断条件。
原文链接:https://blog.csdn.net/weixin_44538423/article/details/89091380

2.谈一谈float a=1.1;有什么问题;
精度类型不一样,float在计算机内部一般用32位二进制表示,而double用64位表示,相对精度更高。至于报错,是由于java默认浮点类型字面量为double类型,所以需要做个强制类型转换:float a = (float) 1.1; or float a = 1.1f;

3.float a=1.1; a=a+1;a++; 说一说有什么问题;然后a++ 为什么能自动强转;
Java默认浮点类型为double,无法自动转成float产生报错。
int类型可自动转为float类型。
拓:a+=b 等价于 a=(a.Type)(a+b); //返回的是a类型,强制转换
a=a+b 等价于 a=a+b; //返回类型是a类型与b类型中的最高类型

4.线程和进程的区别,线程的启动方式有哪些;
一、进程与线程的基础区别:
1、进程是资源分配的最小单位,线程是程序执行的最小单位(资源调度的最小单位)
2、进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。
而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。
3、线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC)进行。不过如何处理好同步与互斥是编写多线程程序的难点。
4、但是多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。
参考:https://www.cnblogs.com/zhehan54/p/6130030.html
二、线程进程的区别体现在4个方面:(高级)
1、因为进程拥有独立的堆栈空间和数据段,所以每当启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这对于多进程来说十分“奢侈”,系统开销比较大,而线程不一样,线程拥有独立的堆栈空间,但是共享数据段,它们彼此之间使用相同的地址空间,共享大部分数据,比进程更节俭,开销比较小,切换速度也比进程快,效率高,但是正由于进程之间独立的特点,使得进程安全性比较高,也因为进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。一个线程死掉就等于整个进程死掉。
2、体现在通信机制上面,正因为进程之间互不干扰,相互独立,进程的通信机制相对很复杂,譬如管道,信号,消息队列,共享内存,套接字等通信机制,而线程由于共享数据段所以通信机制很方便。
3、体现在CPU系统上面,线程使得CPU系统更加有效,因为操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。
4、体现在程序结构上,举一个简明易懂的列子:当我们使用进程的时候,我们不自主的使用if else嵌套来判断pid,使得程序结构繁琐,但是当我们使用线程的时候,基本上可以甩掉它,当然程序内部执行功能单元需要使用的时候还是要使用,所以线程对程序结构的改善有很大帮助。
原文链接:https://blog.csdn.net/qinian8/article/details/100779193
三、启动线程方法
1、继承Thread类
通过Thrad子类启动线程步骤
(1)创建Thraed子类,重写run方法,run方法的函数体就是这个线程的执行逻辑
(2)在主线程中(主函数中)创建Thraed子类的对象
(3)对象调用start()方法,代表启动线程。
2、实现Runnable接口
(1)创建实现Runnable接口的实现类,并在里面重写run方法
(2)在主线程中创建实现类的实例,然后以这个实例作为参数来创造Thread类的实例。
(3)最后是Thread实例调用start()方法来启动子线程

5.线程有哪些状态,他们是通过哪些方法相互转换的;
一、Java 语言中线程共有六种状态。
NEW(初始化状态)
RUNNABLE(可运行 / 运行状态)
BLOCKED(阻塞状态)
WAITING(无限时等待)
TIMED_WAITING(有限时等待)
TERMINATED(终止状态) 在操作系统层面,Java 线程中的 BLOCKED、WAITING、TIMED_WAITING 是一种状态(休眠状态)。即只要 Java 线程处于这三种状态之一,就永远没有 CPU 的使用权。
如图: 在这里插入图片描述二、Java 中线程的状态的转变
(1)NEW 到 RUNNABLE 状态
Java 刚创建出来的 Thread 对象就是 NEW 状态,不会被操作系统调度执行。从 NEW 状态转变到 RUNNABLE 状态调用线程对象的 start() 方法就可以了。
(2)RUNNABLE 与 BLOCKED 的状态转变
synchronized 修饰的方法、代码块同一时刻只允许一个线程执行,其他线程只能等待,等待的线程会从 RUNNABLE 转变到 BLOCKED 状态。
当等待的线程获得 synchronized 隐式锁时,就又会从 BLOCKED 转变到 RUNNABLE 状态。
在操作系统层面,线程是会转变到休眠状态的,但是在 JVM 层面,Java 线程的状态不会发生变化,即 Java 线程的状态会保持 RUNNABLE 状态。JVM 层面并不关心操作系统调度相关的状态,因为在 JVM 看来,等待 CPU 使用权(操作系统层面处于可执行状态)与等待 I/O(操作系统层面处于休眠状态)没有区别,都是在等待某个资源,都归入了 RUNNABLE 状态。
Java 在调用阻塞式 API 时,线程会阻塞,指的是操作系统线程的状态,并不是 Java 线程的状态。
(3) RUNNABLE 与 WAITING 的状态转变
获得 synchronized 隐式锁的线程,调用无参数的 Object.wait() 方法,状态会从 RUNNABLE 转变到 WAITING;调用 Object.notify()、Object.notifyAll() 方法,线程可能从 WAITING 转变到 RUNNABLE 状态。
调用无参数的 Thread.join() 方法。join() 是一种线程同步方法,如有一线程对象 Thread t,当调用 t.join() 的时候,执行代码的线程的状态会从 RUNNABLE 转变到 WAITING,等待 thread t 执行完。当线程 t 执行完,等待它的线程会从 WAITING 状态转变到 RUNNABLE 状态。
调用 LockSupport.park() 方法,线程的状态会从 RUNNABLE 转变到 WAITING;调用 LockSupport.unpark(Thread thread) 可唤醒目标线程,目标线程的状态又会从 WAITING 转变为 RUNNABLE 状态。
(4)RUNNABLE 与 TIMED_WAITING 的状态转变
Thread.sleep(long millis)
Object.wait(long timeout)
Thread.join(long millis)
LockSupport.parkNanos(Object blocker, long deadline)
LockSupport.parkUntil(long deadline)
TIMED_WAITING 和 WAITING 状态的区别,仅仅是调用的是超时参数的方法。
(5)RUNNABLE 到 TERMINATED 状态
线程执行完 run() 方法后,会自动转变到 TERMINATED 状态
执行 run() 方法时异常抛出,也会导致线程终止
Thread类的 stop() 方法已经不建议使用

6.说说你所理解的jvm模型;
jvm:java虚拟机,java的核心与基础,用来运行java的程序
1、java程序的运行过程
1)java源文件被编译器编译成.class文件
2).class文件被类加载器加载至内存//--------类加载器:将.class文件加载至内存并且生成相应的class对象
3)执行
2、jvm程序执行的顺序
加载.class文件>>>>管理分配内存>>>>执行垃圾收集
java语言的特点就是平台的无关性:
java虚拟机在执行字节码时,把字节码解释成具体平台的机器指令,这也就是java能够“一次编译,到处运行”的原因
原文链接:https://blog.csdn.net/qq_40757296/article/details/82728972

7.jvm的垃圾回收机制;
一、JVM GC回收哪个区域内的垃圾?
JVM GC只回收堆区和方法区内的对象
虚拟机栈、程序计数器、本地方法栈为线程私有,不需要回收
二、JVM GC什么时候执行?
伊甸区满的时候,执行Young GC
老年区满的时候,执行Full GC
三、如何判断一个对象是否可以被回收?
1、引用计数法(有缺陷,无法解决循环引用问题,JVM 没有采用)
2、可达性分析(解决了引用计数的缺陷,被 JVM 采用)
四、什么是引用计数法?
对象被引用一次,计数器+1,失去引用,计数器-1,当计数器在一段时间内为0时,即认为该对象可以被回收了。
(无法解决相互引用的问题,例如:A引用B,B引用A,它们永远都不会再被使用)
五、什么是可达性分析?
通过一系列的称为 “GC Roots” 的对象作为起始点,从这些节点开始向下搜索,所有所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是不可用的
六、Java中可以作为GC ROOT的对象有哪些?
1、虚拟机栈中引用的对象(本地变量表)
2、方法区中静态属性引用的对象
3、方法区中常量引用的对象
4、本地方法栈中引用的对象(Native对象)
七、JVM中将对象的引用分为了四种类型
1、强引用:new出来的对象都是强引用,GC无论如何都不会回收,即使抛出OOM异常。
2、软引用:只有当JVM内存不足时才会被回收。
3、弱引用:只要GC,就会立马回收,不管内存是否充足。
4、虚引用:可以忽略不计
八、什么是分代回收?
对于新生代内存的回收使用Young GC主要采用复制算法。
而对于老年代的回收使用Full GC,大多采用标记-整理算法。
九、为什么需要分带回收?
JVM为了优化对内存的回收
十、常见的GC算法
1、复制(停止-复制 效率低,需要的空间大,优点,不会产生碎片)
2、标记-清除(标记 - 清除算法 速度较快,占用空间少,标记清除后会产生大量的碎片)
3、标记-压缩(在标记-清除的基础上移动数据,避免产生内存碎片)
十一、复制算法
复制算法采用的方式为从根集合进行扫描,将存活的对象移动到一块空闲的区域
当存活的对象较少时,复制算法会比较高效(新生代的Eden区就是采用这种算法)
十二、标记-清除
该算法采用的方式是从根集合开始扫描,对存活的对象进行标记,标记完毕后,再扫描整个空间中未被标记的对象,并进行清除。标记-清除动作不需要移动对象,且仅对不存活的对象进行清理,在空间中存活对象较多的时候,效率较高,但由于只是清除,没有重新整理,因此会造成内存碎片。
十三、标记-压缩
该算法与标记-清除算法类似,都是先对存活的对象进行标记,然后清除未被标记的对象,但是在清除后会把活的对象向左端空闲空间移动,然后再更新其引用对象的指针,该算法避免了标记-清除的碎片问题,但由于需要进行移动,因此成本也增加了。(该算法适用于老年代)
十四、垃圾回收器简介
每一个回收器都存在Stop The World 的问题,只不过各个回收器在Stop The World 时间优化程度、算法的不同
十五、常见的垃圾收集器
1、Serial (新生代)
2、ParNew (新生代)
3、ParallelScavenge(新生代)
4、SerialOld (老年代)
5、ParallelOld(老年代)
6、CMS (老年代)
7、G1 (新生代和老年代)
CMS的一大特点,就是用两次短暂的暂停来代替串行或并行标记整理算法时候的长暂停。
CMS的缺点
1、内存碎片
2、需要更多的CPU资源
3、需要更大的堆空间
G1既可以回收新生代,又可以回收老年代

8.根据他的表写sql语句;

9.问了几个常用的Linux命令 查文件 查看内存;
一、查文件
(1)find命令
例如:find / -name mysql 这句命令的意思是在根目录下按名字查找文件夹名叫mysql的文件夹。
find /usr/local/mysql -name *.bin 这句命令的意思是在目录“/usr/local/mysql”中搜索以.bin结尾的所有文件。说明:当mysql开启增量备份的时候,会生成很多.bin结尾的文件。
(2)locate命令
例如:locate *.log 这句命令的意思是查找后缀为.log的文件
locate /etc/my 搜索etc目录下所有以my开头的文件
注意:locate命令要比find -name快得多,原因在于它不搜索具体目录,而是搜索一个数据库/var/lib/mlocate/mlocate.db 。为了避免mlocate.db数据库因为更新操作(如添加修改删除)没来得及更新,在使用该命令前应执行一次“updatedb”。
(3)whereis命令
例如:whereis tomcat 显示结果“/usr/local/tomcat”通过这句命令可以显示tomcat的位置。
二、查看内存
用 ‘top -i’ 看看有多少进程处于 Running 状态,可能系统存在内存或 I/O 瓶颈,用 free 看看系统内存使用情况,swap 是否被占用很多,用 iostat 看看 I/O 负载情况…

10.问了一下数据结构,在hashmap中如何根据key找到value;
根据Map的定义,我们可以知道Map是一组键值对,且key是唯一的,对应的value有且只有一个,但是相同的value可能对应不同的key。如果我们想通过key获取value,可以map.get(key)获得value。而如果需要通过value获取对应的key,则需要自己实现对应的方法。
下面,提供两种方法实现此需求。
方法1:

public static Object getKey(Map map, Object value){
    List<Object> keyList = new ArrayList<>();
    for(Object key: map.keySet()){
        if(map.get(key).equals(value)){
            keyList.add(key);
        }
    }
    return keyList;
}

方法2,通过引入entrySet和Iterator:

public static Object getKey(Map map, Object value){
    Set set = map.entrySet(); //通过entrySet()方法把map中的每个键值对变成对应成Set集合中的一个对象
    Iterator<Map.Entry<Object, Object>> iterator = set.iterator();
    ArrayList<Object> arrayList = new ArrayList();
    while(iterator.hasNext()){
        //Map.Entry是一种类型,指向map中的一个键值对组成的对象
        Map.Entry<Object, Object> entry = iterator.next();
        if(entry.getValue().equals(value)){
            arrayList.add(entry.getKey());
        }
    }
    return arrayList;
}

原文链接:https://blog.csdn.net/u014259820/article/details/78835739

11.项目中遇到过什么难题;

发布了18 篇原创文章 · 获赞 4 · 访问量 921

猜你喜欢

转载自blog.csdn.net/weixin_43698561/article/details/104238186