ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2021-04-02

2021-04-13 22:57:43  阅读:101  来源: 互联网

标签:02 Java String 04 对象 s1 equals 2021 方法


目录


Java基础面试题笔记(一)

1、面向对象的特征有哪些方面?

2、访问修饰符 public,private,protected,以及不写(默认)时的区别?

3、String 是最基本的数据类型吗?

4、float f=3.4;是否正确?

5、short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?

6、Java 有没有 goto?

7、int 和 Integer 有什么区别?

8、&和&&的区别?

9、解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法。

10、Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?

11、switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上?

12、用最有效率的方法计算 2 乘以 8?

13、数组有没有 length()方法?String 有没有 length()方法?

14、在 Java 中,如何跳出当前的多重嵌套循环?

15、构造器(constructor)是否可被重写(override)?

16、两个对象值相同(x.equals(y) == true),但却可有不同的 hashcode,这句话对不对?

17、是否可以继承 String 类?

18、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

19、String 和 StringBuilder、StringBuffer 的区别?

20、重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?


答案与解析

1、面向对象的特征有哪些方面?
要点:封装、继承、多态展开详述

抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。

继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段(如果不能理解请阅读阎宏博士的《Java 与模式》或《设计模式精解》中关于桥梁模式的部分)。

封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口(可以想想普通洗衣机和全自动洗衣机的差别,明显全自动洗衣机封装更好因此操作起来更简单;我们现在使用的智能手机也是封装得足够好的,因为几个按键就搞定了所有的事情)。

多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:当 A 系统访问 B 系统提供的服务时,B系统有多种提供服务的方式,但一切对 A 系统来说都是透明的(就像电动剃须刀是 A 系统,它的供电系统是 B 系统,B 系统可以使用电池供电或者用交流电,甚至还有可能是太阳能,A 系统只会通过 B 类对象调用供电的方法,但并不知道供电系统的底层实现是什么,究竟通过何种方式获得了动力)。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:

1). 方法重写(子类继承父类并重写父类中已有的或抽象的方法);

2). 对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。

2、访问修饰符 public,private,protected,以及不写(默认)时的区别?
在这里插入图片描述

3、String 是最基本的数据类型吗?
要点:八大数据类型,引用类型补充

不是。Java 中的基本数据类型只有 8 个 :byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type),剩下的都是引用类型(referencetype),Java 5 以后引入的枚举类型也算是一种比较特殊的引用类型。

4、float f=3.4;是否正确?
要点:精度损失
不正确。3.4 是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换
float f =(float)3.4;
或 float f =3.4F;

5、short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?
要点:隐式类型转换
short s1 = 1; s1 = s1 + 1;由于 1 是 int 类型,因此 s1+1 运算结果也是 int型,需要强制转换类型才能赋值给 short 型。
而 short s1 = 1; s1 += 1;可以正确编译,因为 s1+= 1;相当于 s1 = (short(s1 + 1);其中有隐含的强制类型转换。
在这里插入图片描述
通过反编译可以看到:
在这里插入图片描述

6、Java 有没有 goto?
要点:保留字与来源
goto 是 Java 中的保留字,在目前版本的 Java 中没有使用。(根据 James Gosling(Java 之父)编写的《The Java Programming Language》一书的附录中给出了一个 Java 关键字列表,其中有goto 和 const,但是这两个是目前无法使用的关键字,因此有些地方将其称之为保留字,其实保留字这个词应该有更广泛的意义,因为熟悉 C 语言的程序员都知道,在系统类库中使用过的有特殊意义的但词或单词的组合都被视为保留字)

7、int 和 Integer 有什么区别?
要点:包装类、自动装箱/拆箱
Java 是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java 为每一个基本数据类型都引入了对应的包装类型(wrapper class),int 的包装类就是 Integer,从 Java 5 开始引入了自动装箱/拆箱机制,使得二者可以相互转换。

Java 为每个基本数据类型提供了包装类型:
基本数据类型: boolean,char,byte,short,int,long,float,double
包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double

相关的面试题还有:

	public static void main(String[] args) {
		Integer a = new Integer(3);
		Integer b = 3;
		int c = 3;
		System.out.println(a == b);  //false
		System.out.println(a == c);  //true
		
		System.out.println("------------");
		
		Integer a1 = 100,a2 = 100,a3 = 150,a4 = 150;
		System.out.println(a1 == a2); 			//true
		System.out.println(a3 == a4);			//false
	}

结局是不是出乎你的意料?
首先来看这行代码
Integer b = 3;
通过反编译后可以看到:
Integer b = Integer.valueOf(3);
代码在执行的时候会自动进行装箱调用到Integer中的valueOf()方法

public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

源码如上,IntegerCache是Integer类中的内部类

private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            ...
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }

        private IntegerCache() {}
    }

原来,在调用valueOf()方法的时候会创建一个[-128,127]的缓存数组,只要数值在这个数组取值范围内,则不会重新创建对象,而是从缓存数组中取出返回
故 a与b是false,因为两者比对的是引用地址
a1与a2是true(都是从缓存数组中去取)
a3与a4是false(重新new一个Integer对象,比对的还是引用地址)
而这个结果
System.out.println(a == c); //true
反编译后:
System.out.println(a.intValue() == c)
则是底层会自动拆箱,比对的是数值

8、&和&&的区别?
要点
&:存在两种用法:按位与 和 逻辑与
按位与是用来操作二进制
逻辑与用来进行逻辑判断,即使表达式 a&b a不成立,也会判断b
&&:短路与
表达式 a&b ,a不成立,直接返回false并不对表达式b进行判断
补充 |与 || 也是同理
&运算符有两种用法:
(1)按位与;
(2)逻辑与。&&运算符是短路与运算。逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是true 整个表达式的值才是 true。&&之所以称为短路运算是因为,如果&&左边的表达式的值是 false,右边的表达式会被直接短路掉,不会进行运算。很多时候我们可能都需要用&&而不是&,例如在验证用户登录时判定用户名不是 null 而且不是空字符串,应当写为:username != null &&!username.equals(“”),二者的顺序不能交换,更不能用&运算符,因为第一个条件如果不成立,根本不能进行字符串的 equals 比较,否则会生 NullPointerException 异常。注意:逻辑或运算符(|)和短路或运算符(||)的差别也是如此。

9、解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法。

栈(JVM Stack):描述了java方法执行的内存模型,每个方法执行时都会同步创建一个方法栈,用来存储局部变量表、方法出口、动态链接、操作栈等信息,当方法操作完毕后就销毁

堆(Heap):被所有线程所共享的一块内存区域,jvm启动时创建,所有对象的实例以及数组都要在堆上分配内存,使用 new 关键字就表示在堆空间中开辟一块新的存储空间

方法区(Method Area):线程共享的内存区域,存储已被虚拟机加载的类信息,常量,静态变量、即时编译器编译后的代码数据等

常量池:方法区中专门存储常量的地方
编译常量池:把字节码加载进JVM的时候,存储的是字节码相信息
运行常量池:存储常量数据

通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用 JVM 中的栈空间;而通过 new 关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域,由于现在的垃圾收集器都采用分代收集算法,所以堆空间还可以细分为新生代和老生代,再具体一点可以分为 Eden、Survivor(又可分为 From Survivor 和 To Survivor)、Tenured;方法区和堆都是各个线程共享的内存区域,用于存储已经被 JVM 加载的类信息、常量、静态变量、JIT 编译器编译后的代码等数据;程序中的字面量(literal)如直接书写的 100、”hello”和常量都是放在常量池中,常量池是方法区的一部分,。栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,栈和堆的大小都可以通过 JVM的启动参数来进行调整,栈空间用光了会引发 StackOverflowError,而堆和常量池空间不足则会引发 OutOfMemoryError。

String str = new String("hello");

上面的语句中变量 str 放在栈上,用 new 创建出来的字符串对象放在堆上,而”hello”这个字面量是放在方法区的。

补充 1:较新版本的 Java(从 Java 6 的某个更新开始)中,由于 JIT 编译器的发展和”逃逸分析”技术的逐渐成熟,栈上分配、标量替换等优化技术使得对象一定分配在堆上这件事情已经变得不那么绝对了。
补充 2:运行时常量池相当于 Class 文件常量池具有动态性,Java 语言并不要求常量一定只有编译期间才能产生,运行期间也可以将新的常量放入池中,String类的 intern()方法就是这样的。

String s1 = new StringBuilder("go").append("od").toString();
System.out.println(s1.intern() == s1);
String s2 = new StringBuilder("ja").append("va").toString();
System.out.println(s2.intern() == s2);

上述代码执行结果为: true、false
原因可参考:intern()方法.

10、Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?
Math.round(11.5)的返回值是 12,Math.round(-11.5)的返回值是-11
看源码~
在这里插入图片描述

11、switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上?
在 Java 5 以前,switch(expr)中,expr 只能是 byte、short、char、int。从 Java5 开始,Java 中引入了枚举类型,expr 也可以是 enum 类型,从 Java 7 开始,expr 还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。
源码:
在这里插入图片描述
反编译后:
在这里插入图片描述
由此可知:即使现在能支持String类型,其底层依然是比较的int类型

12、用最有效率的方法计算 2 乘以 8?
位运算:2<<3

13、数组有没有 length()方法?String 有没有 length()方法?
数组没有 length()方法 ,有 length 的属性。
String 有 length()方法。
JavaScript中,获得字符串的长度是通过 length 属性得到的,这一点容易和 Java 混淆。

14、在 Java 中,如何跳出当前的多重嵌套循环?
continue:跳过当前循环,进入下一次循环
break:终止当前所在循环
控制外层循环,给外层循环起别名,如:

 XX: for(){
	for(){
		if(){
			break XX;
		}
	}
  }

return:结束所在的方法

15、构造器(constructor)是否可被重写(override)?
要点:重载与重写、构造器
重载:同一个类中,方法名称相同,参数列表不同(方法设计问题)
方法的重载与方法的返回值无关
作用:屏蔽同一功能方法因为参数不同所造成的方法名称不同
重写:子类定义一个与父类方法名称、参数列表、返回值相同的方法(也称方法覆盖)
被重写的方法控制权限不能比父类更加严格
作用:父类中的方法功能不足,但是子类必须使用这个方法名称时

构造器不能被继承,因此不能被重写,但可以被重载。

16、两个对象值相同(x.equals(y) == true),但却可有不同的 hashcode,这句话对不对?
不对,如果两个对象 x 和 y 满足 x.equals(y) == true,它们的哈希码(hash code)应当相同。Java 对于 eqauls 方法和 hashCode 方法是这样规定的:

(1)如果两个对象相同(equals 方法返回 true),那么它们的 hashCode 值一定要相同;

(2)如果两个对象的 hashCode 相同,它们并不一定相同。当然,你未必要按照要求去做,但是如果你违背了上述原则就会发现在使用容器时,相同的对象可以出现在 Set 集合中,同时增加新元素的效率会大大下降(对于使用哈希存储的系统,如果哈希码频繁的冲突将会造成存取性能急剧下降)。

补充:equals 方法的:首先 equals 方法必须满足自反性(x.equals(x)必须返回 true)、对称性(x.equals(y)返回 true 时,y.equals(x)也必须返回 true)、传递性(x.equals(y)和 y.equals(z)都返回 true 时,x.equals(z)也必须返回 true)和一致性(当 x 和 y 引用的对象信息没有被修改时,多次调用 x.equals(y)应该得到同样的返回值),而且对于任何非 null 值的引用 x,x.equals(null)必须返回 false。

实现高质量的 equals 方法的诀窍包括:

(1) 使用==操作符检查”参数是否为这个对象的引用”;

(2) 使用 instanceof 操作符检查”参数是否为正确的类型”;

(3) 对于类中的关键属性,检查参数传入对象的属性是否与之相匹配;

(4) 编写完 equals方法后,问自己它是否满足对称性、传递性、一致性;

(5) 重写 equals 时总是要重写 hashCode;

(6) 不要将 equals 方法参数中的 Object 对象替换为其他的类型,在重写时不要忘掉@Override 注解。

17、是否可以继承 String 类?
String 类是 final 类,不可以被继承。

补充:继承 String 本身就是一个错误的行为,对 String 类型最好的重用方式是关联关系(Has-A)和依赖关系(Use-A)而不是继承关系(Is-A)。

18、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
是值传递。Java 语言的方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用过程中被改变,但对对象引用的改变是不会影响到调用者的。

java中基本数据类型传递的是值的副本,引用类型传递的是引用地址值

类似的面试题

public class Example {
        String srt = new String("good");
        char[] ch = {'a','b','c'};
     public static void main(String[] args){
         Example ex = new Example();
         ex.change(ex.srt, ex.ch);
         System.out.print(ex.srt + " and ");
         System.out.print(ex.ch);
    }

    private void change(String str, char[] ch) {
            str = "test ok";
            ch[0] = 'g';
    }
}

上面程序输出的结果是:
A:good and abc
B:good and gbc
C:test ok and abc
D:test ok and gbc

答案是:B
原文链接.

19、String 和 StringBuilder、StringBuffer 的区别?
String是只读字符串,这意味着String引用的字符串内容是不能改变的;
StringBuilder/StringBuffer类表示的字符串对象是可以直接修改的
StringBuilder是java5引入的,它与StringBuffer的方法完全相同,区别在与它是在单线程环境下使用的,所有方法都没有被synchronized 修饰,因此它的效率也要比StringBuffer要高

补充面试题:
什么情况下用+运算符进行字符串连接比调用
StringBuffer/StringBuilder 对象的 append 方法连接字符串性能更好?

要点:字符串的+操作其本质是创建了 StringBuilder 对象进行 append 操作,然后将拼接后的 StringBuilder 对象用toString 方法处理成 String 对象,这一点可以用 javap -c StringEqualTest.class命令获得 class 文件对应的 JVM 字节码指令就可以看出来。

20、重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?
重载:在同一类中,方法名相同,方法参数不同(无关返回值)
重写:在子类与父类中,方法签名必须相同,重写方法权限不能超过父类
两者都是实现多态的方法,区别在于重载是编译时的多态性,重写是运行时的多态性


面试题与解析来源“时代名猿”公众号,做了一些自己的笔记与理解~

标签:02,Java,String,04,对象,s1,equals,2021,方法
来源: https://blog.csdn.net/qq_47482077/article/details/115366697

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有