黄高涛的面试总结题目

java是被设计成和具体的硬件无关的。
因此,java的64位版本和32位版本的int都是32位的范围。

int 和 Integer 哪个会占用更多的内存?

Integer 对象会占用更多的内存。Integer 是一个对象,需要存储对象的元数据。

但是 int 是一个原始类型的数据,所以占用的空间更少。

请看下面的代码:

double a = 2.0, b = 1.1, c = 0.9;

if (a - b == c) {

System.*out*.println(“YES!”);

} else {

System.*out*.println(“NO!”);

}

以上代码输出的结果是多少呢?你认为是*“YES*!吗?那么,很遗憾的告诉你,不对,以上代码会输出“NO。为什么会这样呢?其实这是由实型数据的存储方式决定的。我们知道实型数据在内存空间中是近似存储的,所以2.0-1.1的结果不是0.9,而是0.88888888889。所以在做实型数据是否相等的判断时要非常的谨慎。一般来说,我们不建议在代码中直接判断两个实型数据是否相等,如果一定要比较是否相等的话我们也采用以下方式来判断:

if(Math.abs(a-b)<1e-5){

*//*相等

}else{

*//*不相等

}

上面的代码判断ab之差的绝对值是否小于一个足够小的数字,如果是,则认为ab相等,否则,不相等。

如果是float类型的就为OK

Java中double或float运算丢失精度问题

计算机内部是用的是二进制码,当输入float或者double类型的十进制数进行运算的时候,会先转化成二进制数再进行运算,最后在转化为十进制输出。然而有些数字不能完全转化成二进制,计算机只能将结果无限趋近于原本十进制的数值,故会出现精度丢失的问题

public static void main(String[] args) {
	double a = 0.05;
	double b = 0.07;
	double c = a+b;
	System.out.println(c);
	float x = 0.05f;
	float y = 0.07f;
	float z = x+y;
	System.out.println(z);
}

输出

0.120000000000000001

0.120000000005

不可变对象

https://www.cnblogs.com/yanggb/p/12453857.html

指的是对象一旦被创建后,对象所有的状态及属性在其生命周期内不会发生任何变化。

就是一个对象在创建后,不能对该对象进行任何更改。

类不提供任何setter方法,并且成员变量value是基本数据类型,getter方法返回的是value的拷贝,所以一旦此类实例被创建后,该实例的状态无法再进行更改,因此该类具备不可变性。

ArrayList 和 HashMap 的默认大小是多数?

ArrayList 的默认大小是 10 个元素,HashMap 的默认大小是16个元素(必须是2的幂)。

扩容增量:原容量的 0.5倍+1

如 ArrayList的容量为10,一次扩容后是容量为16

HashMap:默认初始容量为16

为何是16:16是2^4,可以提高查询效率,另外,32=16<<1 -->至于详细的原因可另行分析,或分析源代码)

加载因子为0.75:即当 元素个数 超过 容量长度的0.75倍 时,进行扩容

扩容增量:原容量的 1 倍

如 HashSet的容量为16,一次扩容后是容量为32

为什么是16?

应该是为了减少散列碰撞和避免空间浪费吧,java的散列函数是通过hashcode和length-1计算的,他的容量必须是2的n次方。如果一开始是14二进制1110,最后一位为0,导致散列函数计算后0001,0101等永远不会出现,位置不能存放元素,空间浪费,增加了散列碰撞。散列函数的设计就是围绕减少散列碰撞和使元素分布均匀(整个 数组都能存放)而设计的。

hash,一般翻译做“散列”,直接音译位“哈希”

就是把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值。

两个不同的输入值,根据同一散列函数计算出的散列值相同的现象叫做碰撞

java线程安全问题静态成员变量、实例成员变量、局部变量

静态成员变量**:**线程非安全(无论单例或者非单例皆不安全)。

静态变量即类变量,位于方法区,为所有对象共享,共享一份内存,一旦静态变量被修改,其他对象均对修改可见,故线程非安全。

实例成员变量单例模式(只有一个对象实例singleton存在)线程非安全,非单例线程安全。

实例变量为对象实例私有,在虚拟机的堆heap中分配,若在系统中只存在一个此对象的实例,在多线程环境下,“犹如”静态变量那样,被某个线程修改后,其他线程对修改均可见,故线程非安全(如,springmvc controller是单例的,非线程安全的);如果每个线程执行都是在不同的对象中,那对象与对象之间的实例变量的修改将互不影响,故线程安全(如,struts2 action默认是非单例的,每次请求在heap中new新的action实例,故struts2 action可以用实例成员变量)。

局部变量线程安全**(线程封闭性Thread Confinement)。**

每个线程执行时将会把局部变量放在各自栈帧的工作内存中,线程间不共享,故不存在线程安全问题。

1、 *Java中堆和栈的区别?*

JVM 中堆和栈属于不同的内存区域,使用目的也不同。栈常用于保存方法帧和局部变量,而对象总是在堆上分配。栈通常都比堆小,也不会在多个线程之间共享,而堆被整个 JVM 的所有线程共享。

Byte、byte[]、和String的转换

  1. //Original String
  2. ​ String string = “hello world”;
  3. //Convert to byte[]
  4. ​ byte[] bytes = string.getBytes();
  5. //Convert back to String
  6. ​ String s = new String(bytes);

a+=b 和a=a+b

1、会编译报错 5默认为int类型的变量 a为short类型 相加会向上转型为int变量,赋值给short 类型的a变量

解决方法:强制类型转换

 short a=4;
     a=a+5;

2、能顺利打印

+=是java中的一个运算符,不是两个,程序在执行“+=”时,会自动向高精度进行数据类型转换。所以下面的程序在执行时编译器没有报错。

 short a=4;
     a+=5;

i++是线程安全的吗

因为每个线程都有自己的工作内存,每个线程需要对共享变量操作的时候必须先把共享变量从主内存load到自己的工作内存,等完成对共享变量的操作时再保存到主内存。

如果一个线程运算完成后还没刷到主内存,此时这个共享变量的值被另一个线程从主内存读取到了,这个时候读取的数据就是脏数据了,他会覆盖其他线程计算的值。

使用volatile 让内存可见也无法解决此问题,因为vilatile只能保证可见性,不能保证原子性。多个线程同时读取这个共享变量的值,就算保证其他线程修改的可见性,也不能保证线程之间读取到同样的值,然后相互覆盖对方的值的情况。

例如 a、b线程都读取到了 i=1,都对i+1 本来应该是3却成了2

Spring的自动装配模式

数据库引擎

两数运算结果保留两位小数

static float scale(Float floatValue)
    {
        DecimalFormat format = new DecimalFormat("#.00");
        String scaled = format.format(floatValue);
        System.out.println(scaled);
        return Float.parseFloat(scaled);
    }

  static   double scale(Double doubleValue)
    {
        DecimalFormat format = new DecimalFormat("#.00");
        String scaled = format.format(doubleValue);
        System.out.println(scaled);
        return Double.parseDouble(scaled);
    }
}

抽象类和接口的区别

1.抽象类可以有构造方法,接口中不能有构造方法。

2.抽象类中可以有普通成员变量,接口中没有普通成员变量

3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。

\4. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。

\5. 抽象类中可以包含静态方法,接口中不能包含静态方法

\6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。

\7. 一个类可以实现多个接口,但只能继承一个抽象类

水仙花数

    for (int i = 100; i < 1000; i++) {

            int b = i/100;


            int s = i/10-b*10;
            int g = i-(b*100+s*10);

            if(b*b*b+s*s*s+g*g*g==i){
                System.out.println(i);
            }

Tomcat

在Windows服务器上用不同版本JDK启动多个Tomcat

在一台Windows Server 服务器,上面部署了jdk1.7,有一个tomcat7.0基于jdk1.7的应用在运行。

目标:
这台服务器下还需要部署一个tomcat8,需要用到jdk1.8运行项目,这样我们需要在一台服务器上部署2个jdk及2个tomcat,并且分别让他们应用不同的jdk来运行,即jdk1.8对应tomcat8,jdk1.7对应tomcat7。

操作过程:

1.我们先到oracle官网上,把基于windows x64的jdk1.8下载好,然后上传到服务器上,并且安装。

2.我们需要配置一下环境变量,主要新增这么几个:JAVA_HOME、CATALINA_HOME、CLASSPATH

将这几个环境变量新增,并且名称修改为JAVA_HOME1,CATALINA_HOME1,CLASSPATH1

3.将参数添加到环境变量中,分别为:

JAVA_HOME1:C:\Program Files\Java\jdk1.8.0

CATALINA_HOME1:D:\software\apache-tomcat-8

CLASSPATH1:.;%JAVA_HOME1%\lib\dt.jar;%JAVA_HOME1%\lib\tools.jar;

4.我们到tomcat8的bin下,将所有后缀为.bat的文件打开,进行编辑和替换。

bat文件中所有JAVA_HOME、CATALINA_HOME、CLASSPATH修改为JAVA_HOME1、CATALINA_HOME1、CLASSPATH1。

5.此处注意,在新部署tomcat的时候,要修改server.xml里的端口,不要跟之前的有冲突,会导致tomcat端口占用,还有一种情况就是当执行shutdown.bat的时候,如果两个tomcat的shutdown端口一样,那么关闭一个另外一个tomacat也会被关闭。

6.分别启动不同的tomcat,可以在catalina.log中看到分别调用了不同的jdk

temp文件

(存放Tomcat执行时的临时文件

temp目录用户存放tomcat在运行过程中产生的临时文件。(清空不会对tomcat运行带来影响)

Webapps文件

webapps目录用来存放应用程序,当tomcat启动时会去加载webapps目录下的应用程序。可以以文件夹、war包、jar包的形式发布应用。

work文件

存放Tomcat运行时产生的class文件

work目录用来存放tomcat在运行时的编译后文件,例如JSP编译后的文件。清空work目录,然后重启tomcat,可以达到清除缓存的作用。

构造方法

构造方法不能调用构造方法,但是可以在构造方法的第一行调用this(); 代表构造方法

关键字

sizeof、native不是java关键字

抽象

抽象方法不能同时是

static、native、synchronized

抽象类是可以继承实体类的

Linux常用命令

servlet和filter

合法标识符

File类

mysql group by 的用法

所有select 字段,除了聚合函数中的字段,都必须出现在GROUP BY 中。

例如:SELECT name,age,max(salary) FROM t_employee GROUP BY name,age

salary 字段可以不用出现在 GROUP BY 中

构造器

构造器(override)不能被继承,因此不能重写overriding,但是可以被重载overloading

接口和抽象类的区别,

接口和抽象类中的变量

存在使i+1<i时,i为多少

在JDK中,整形类型是有范围的,最大值为Integer.MAX_VALUE,即2147483647,最小值为Integer.MIN_VALUE即-2147483648。
对整形最大值加1,2147483648(越界了),那么此时值为多少呢?结果是-2147483648,即是Integer.MIN_VALUE。

类似的,对Integer.MIN_VALUE取反或者取绝对值呢?仍为Integer.MIN_VALUE,因为值为-2147483648,绝对值2147483648超过Integer.MAX_VALUE 2147483647。
所以就有以下结果论:
1.Integer.MAX_VALUE + 1=Integer.MIN_VALUE
2.Math.abs(Integer.MIN_VALUE) = Integer.MIN_VALUE(直接返回该值 -2147483648
3.Long,short,byte的结论是相同的。

由上面的解析可以知道:
假设i是int类型,那么当i=2^32-1时,i+1数据溢出变成负数,就达成了条件i+1 < i,其他类型同理

接口中可以有静态方法

只能用public修饰 或者不写

方法的重载

 public int aa(int a ,int b){
        return  a;
    }
    
    
    public static void aa(int a,String b){
        
    }

可以这样实现重载,可见,重载条件 :方法名相同,参数列表不同

返回值类型和修饰符可以相同,也可以不相同

Java中会存在内存泄漏吗

内存泄漏是指不再被使用的对象或者变量一直被占据在内存中。但是java中有垃圾回收机制,它能够将不再被使用的对象,自动从内存中清除。

即使这样,java中也存在着内存泄漏的情况:

一:当长生命周期的对象持有短生命周期的对象的引用,就很可能发生内存泄漏。尽管短生命周期的对象已经不再需要,但是长生命周期的对象一直持有它的引用导致其无法被回收。例如,缓存系统;加载一个对象放在缓存系统中,一直不去使用这个对象,但是它一直被缓存引用,所以不会被回收导致缓存泄漏。

检查java中的内存泄漏,一定要将程序各个分支情况都完成执行至结束,然后看其是否被使用过,如果没有才能判定这个对象属于内存泄漏。

二:当一个对象被存储进HashSet集合中,就不可修改这个对象中用于计算哈希值的属性了。否则,对象修改后的哈希值与刚添加进HashSet集合时的哈希值不一样,此时如果将当前对象的引用作为参数,用contains方法判断对象是否存在,则会返回找不到对象的结果。这会导致无法从HashSet单独删除当前对象,造成内存泄漏

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值