2021校招一面题目及答案

1.String类型的几种存储方式,是否是线程安全的,两个字符串相加是否是新的实例?

  • 有二种存储方式:
    1. String str=“test”,这是第一种创建的“test”保存在(方法区)字符串常量池中,string是final修饰的,所以只能一次赋值不能改变,所以字符串不能改变
    2. String str=new String(“test”),第二种方式在堆中开辟空间,当调用new()方法时,jvm将会调用String的构造函数,同时引用常量池中的test字符串,在堆中创建一个string对象,并返回堆中的引用地址,没当用同样的方法new一个test字符串的时候,就会创建一个String对象,然后指向常量池中的test
  • 是线程安全的:因为String是用final修饰的,只能一次赋值不能改变
  • String str=“a”+“b”:这样的话不产生新的对象,String str= a+b,会创建新的对象:如果右对象参与相加,编译器无法处理,结果就会创建新对象,如果字符直接相加,会先经编译器处理,气且常量使用过就是一个对象,下次使用不产生新的对象
  • tips:因为字符串是不可变的,所以在创建的时候HashCode就被缓存了,不需要重新计算,这就使得字符串会适合作为Map的键,字符串的处理速度要快于其他键对象,这就是HAshMap中键为啥是String字符串类型(把这个顺便说了,面试官会感觉你知识面很广)

2.Stringbuffer用append方式,对象是否发生变化?

  • stringBuffer实际上是一个动态字符串数组,类对象可以多次修改,append()相当于加号不产生新的对象,线程安全的
  • stringBuilder是线程不安全的,但速度上更快

3.Java的值传递

  • 值传递:方法在调用时,实参通过形参把他内容的副本拷贝,传入方法内部,方法内的都是对这个副本的操作,不影响原始值
  • 引用传递:引用是指向真实的地址值,在方法的调用时,实现的地址通过方法的调用传递给形参,在方法体内形参和实参如果都指向同一个内存地址,对形参的操作会影响真实内容,否则不会

4.Java内存区域的划分,线程共享的部分,哪些部分会有溢出的情况?

  • 线程共享的有java堆和方法区,线程独享的都本地方法区、栈、pc寄存器
  • 除了pc寄存器都可能会发生溢出
    • java堆:无限循环new对象,在list中保存防止被gc回收,会报memory leak内存泄漏
    • 方法区:生成大量的动态类,或无线循环调用String 的intern()方法产生不同的String对象实例放到list中,前者测试方法区中非常量池部分,后者测试常量池
    • 虚拟机栈和本地方法区:单线程的话递归调用一个简单方法会抛出StackOverflowError,多线程无线创建线程,被增加内存会抛出OutOfMemoryError

5.final类

  • 不能被继承,不能被覆盖,地址引用和装载在编译时(inline编译)完成执行速度快

tip

  • final 变量必须在声明的时候初始化或者在构造器中初始化
  • 在匿名类中所有的变量都必须是final变量

6.static修饰符

  • static是一个用于修饰成员的修饰符

  • static修饰的成员被所有的对象共享

  • static优于对象存在,static的成员随着类的加载就已经存在了

  • 修饰的成员直接用ClassName.调用

  • 修饰的数据是静态变量共享数据,存储在方法区中,对象共享,一般的成员变量存储在堆内存的对象中,也叫对象的特有数据

浅拷贝

  • 对于基本数据类型,因为基本数据类型是值传递,所以直接将属性赋值给新的对象,其中一个对象修改,不会影响另一个
  • 对于引用类型,接口数组和类,因为类型是引用传递,所以浅拷贝只是把内存地址赋值给了成员变量,他们指向同一内存空间,改变其中一个,会对另一个产生影响

深拷贝

  • 对于基本数据类型和浅拷贝一样
  • 对于引用数据类型,会创建一个新的内存空间然后拷贝里面的内容,所以他们指向不同的内存空间,改变一个,不影响另一个

tips

  • 实现对象的拷贝的类,要实现Cloneable接口,并重写clone()方法

创建线程方式,run和start的区别。几种线程池设计模式

  • 有继承THread类和实现runable接口两种方式
  • 直接调用run方法会沿着主线程来执行方法,调用start方法会调用JVM——StartThread方法去创建一个新的子线程,并通过run 方法启动子线程,run只是thread的一个普通方法

设计模式

  • 主要有单例设计模式、享元设计模式、代理模式、装饰者模式
  • 单例模式:一般有懒汉式、饿汉式、双重检查加锁式几种实现方式
    • 懒汉式:资源不在初始化阶段全部加载或者初始化,而是等到使用的时候才去判断加载,优点,初始化比较快,在运行的时候也只加载一次
    • 饱汉式:所有的资源加载和对象实例化都在初始化阶段,接下来直接使用就行,优点:资源直接加载,运行时性能更高,但资源消耗大,耗时比较长
    • 从安全角度看,不加同步的饿汉式是不安全的,比如两个线程同时调用getInstance方法,那就可能导致并发安全问题,加synchronzied 可实现线程安全,但会降低访问速度,更好的解决方案就是双重加锁式
    • 双重检查加锁:先判断对象是否已经被初始化,再决定要不要加锁。
    • 检查变量是否被初始化(不去获得锁),1如果已被初始化则立即返回。2获取锁。3再次检查变量是否已经被初始化,如果还没被初始化就初始化一个对象。
      执行双重检查是因为,如果多个线程同时了通过了第一次检查,并且其中一个线程首先通过了第二次检查并实例化了对象,那么剩余通过了第一次检查的线程就不会再去实例化对象。
      这样,除了初始化的时候会出现加锁的情况,后续的所有调用都会避免加锁而直接返回,解决了性能消耗的问题。
    • 双重加锁式的实现用到的是volatile关键字,被valatiel修饰的变量,不会被本地线程缓存,所有对该变量的操作都是直接在共享内存(主内存)进行的,从而保证了多个线程的同步安全

mysql的char和varchar的区别;行级锁和表级锁的概念,以及给项目带来的影响

  • char是定长,超过截取,不足补空格,最多存放255个字符
  • varchar是不定长,规定长度内有多少存多少,超出舍去
  • mysql的默认innoDb引擎支持行锁和表锁,而myisam不支持行锁
  • 表锁:不会发生死锁,发生锁冲突的几率高,并发低
    • 有两种模式:表(共享)读锁,表(独占)写锁
    • 读锁会阻塞写,写锁会阻塞读和写
    • myisam不适合做主表的引擎,因为加入写锁后,其他的线程不能做任何操作,大量的更新会使查询很难得到锁,从而造成永久阻塞
  • 行锁:会发生死锁,发生锁冲突几率低,并发高
  • mysql的innodb引擎支持的行锁,与Oracle不同,mysql的行锁通过索引加载的如果没有索引会自动锁全表,那就不是行锁了
  • tips:间隙锁:
    • 进行范围条件检索数据时,对于键值在条件范围内并不存在的记录加锁,就是间接锁
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值