面试题—java基础

文章参考<Java 面试知识点解析(一)——基础知识篇>

1.面向对象的特性有哪些?

封装、继承、多态(硬要多算一个那就是抽象)

  • 封装:将对象的属性私有化,提供公有的方法供外部使用。
  • 继承:是面向对象中软件复用的重要手段,子类继承父类,子类就相当于一种特殊的父类,可以直接或间接的获得父类中的成员。
  • 多态:指同一种行为有不同的表现形态。
    比如说,有一杯水,我不知道它是温的、冰的还是烫的,但是我一摸我就知道了,我摸水杯的这个动作,对于不同温度的水,就会得到不同的结果,这就是多态。
    多态的条件:1)继承;2)重写;3)向上转型。
1.
向上转型:父类的引用指向子类的对象。这种属于自动转换
向下转型:在java中,向下转型则是为了,通过父类强制转换为子类,
从而来调用子类独有的方法(向下转型,在工程中很少用到).

2.为了保证向下转型的顺利完成,在java中提供了一个关键字:instanceof,
通过instanceof可以判断某对象是否是某类的实例,如果是则返回true,
否则为false,

3.多态的体现
父类类型 变量名 = new 子类对象;
变量名.方法名();

扩展:方法具有多态性,变量不具有多态性

  • 抽象:是指从特定的角度出发,从已经存在的一些事物中抽取我们所关注的特性、行为,从而形成一个新的事物的思维过程,是一种从复杂到简洁的思维方式。

2.面向对象和面向过程的区别?

举例:大象装进冰箱。

  • 面向过程:
    打开冰箱–》存储大象 --》关上冰箱
    对于面向过程思想,强调的是过程(动作)。
    语言:C。
  • 面向对象:
    对于面向对象思想,强调的是对象(实体)。
    冰箱打开–》冰箱存储大象 --》冰箱关上
    语言:C++、Java、C#(读音:c sharp)
    特点:
    1、面向对象就是一种常见的思想,符合人们的思考习惯。
    2、面向对象的出现,将复杂的问题简单化。
    3、面向对象的出现,让曾经在过程中的执行者,变成了对象的指挥者。

3.JDK 和 JRE 的区别是什么?

Java 运行时环境(JRE-Java Runtime Environment),它包括 Java 虚拟机、Java 核心类库和支持文件,但并不包含开发工具(JDK-Java Development Kit)——编译器、调试器和其他工具。(即没有编译器和调试器

Java 开发工具包(JDK)是完整的 Java 软件开发包,包含了 JRE,编译器和其他的工具(比如 JavaDoc, Java 调试器),可以让开发者开发、编译、执行 Java 应用程序。

备注:JVM 是 Java 虚拟机,当我们运行一个程序时,JVM 负责将字节码转换为特定机器代码,JVM 提供了内存管理 / 垃圾回收和安全机制等。

4.Java 中覆盖和重载是什么意思?

  • 覆盖(Override)是指子类对父类方法的一种重写,只能比父类抛出更少的异常,访问权限不能比父类的小,被覆盖的方法不能是 private的,否则只是在子类中重新定义了一个新方法。
  • 重载(Overload)表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同。

面试官: 那么构成重载的条件有哪些?
答:参数类型不同、参数个数不同、参数顺序不同。

面试官: 函数的返回值不同可以构成重载吗?为什么?
答:不可以,因为 Java 中调用函数并不需要强制赋值。举例如下:

如下两个方法:

  void f(){}
  int f(){ return 1; }

只要编译器可以根据语境明确判断出语义,比如在 int x = f(); 中,那么的确可以据此区分重载方法。不过, 有时你并不关心方法的返回值,你想要的是方法调用的其他效果 (这常被称为 “为了副作用而调用” ),这时你可能会调用方法而忽略其返回值,所以如果像下面的调用:

f();

此时 Java 如何才能判断调用的是哪一个 f() 呢?别人如何理解这种代码呢?所以,根据方法返回值来区分重载方法是行不通的。

参照<java方法重写规则 重载>

5.抽象类和接口的区别有哪些?

参数抽象类接口
与正常java类的区别除了可以有抽象方法和不能实例化以外,跟普通类一样(用abstract修饰符修饰)接口是完全不同的类型(interface关键字),不能有构造器和初始代码块(指存在类的实体中的代码块),接口定义的是一种公共行为规范
结构细节抽象类必须被继承,抽象类可以有抽象方法也可以没有抽象方法,抽象方法必须被子类重写接口是用来被实现的,接口中的方法都是抽象方法(java8中允许有默认方法、类方法、内部类),都用public访问修饰符修饰。变量用public static final修饰(可以省略不写),抽象方法,public abstract修饰(可以省略不写)
main方法抽象类可以有main方法并且可以执行接口中没有main方法

《ava中抽象类和接口存在的意义与价值》

6.Java 和 C++ 的区别:

解析:虽然我们不太懂C++,但是就是会这么问,尤其是三面(总监级别)面试中。

答:

都是面向对象的语言,都支持封装、继承和多态

指针:Java不提供指针来直接访问内存,程序更加安全

继承: Java的类是单继承的,C++支持多重继承;Java通过一个类实现多个接口来实现C++中的多重继承; Java中类不可以多继承,但是!!!接口可以多继承

内存: Java有自动内存管理机制,不需要程序员手动释放无用内存

7.“static” 关键字是什么意思?

“static” 关键字,静态的。

  • 修饰方法和变量时表示方法和变量是属于类的,可以直接通过类名访问.
  • 修饰代码块,叫做静态代码块,在类加载时执行,主要目的是对静态属性初始化。
  • 被static修饰的内部类,它可以不依赖于外部类实例对象而被实例化,而通常的内部类需要在外部类实例化后才能实例化。(静态内部类是外部类的一个静态成员)

面试官:Java中是否可以覆盖(override)一个 private 或者是 static 的方法?

答:Java 中 static 方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而 static 方法是编译时静态绑定的。static 方法跟类的任何实例都不相关,所以概念上不适用。

Java 中也不可以覆盖 private 的方法,因为 private 修饰的变量和方法只能在当前类中使用,如果是其他的类继承当前类是不能访问到 private 变量或方法的,当然也不能覆盖。

扩展阅读<重新认识java(六) ---- java中的另类:static关键字(附代码块知识)>

8."final"关键字什么意思

"final"关键字,最终的

  • 修饰类:类不能被继承。
  • 修饰变量:变量的初始值不可被改变。
  • 修饰方法:方法不能被重写。

扩展:修饰变量时,如果在定义变量时指定了初始值,且初始值在编译时被确定下来(如果调用用了方法就不会在编译时被确定下来),则这个变量就是宏变量(相当于一个直接值),编辑器会把所有用到宏变量的地方直接替换成宏变量的值。

9.java中的访问修饰符有哪些?

访问权限子类其他包说明
public(对任何人都是可用的)
protect(继承的类可以访问以及和private一样的权限)
default(包访问权限,即在整个包内均可被访问)
private(除类型创建者和类型的内部方法之外的任何人都不能访问的元素)

10.什么是内部类

在 Java 中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类。
注意:外部类只能用public和默认修饰符修饰,内部类还可以用protected、private、static修饰。非静态内部类不能有静态成员。一个java源文件中只能有一个public类。

1) 成员内部类:成员内部类是最普通的内部类,它作为一个类的成员。
成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:

外部类.this.成员变量
外部类.this.成员方法

外部类访问内部类成员时,必须先创建内部类的对象,然后通过对象实例访问。
其他类访问内部类时,必须先创建外部类的实例,在创建内部类的实例,比如:

new Outter().new Inner()

2) 局部内部类
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
注意: 局部内部类就像是方法里面的一个局部变量一样,是不能有 public、protected、private 以及 static 修饰符的。
3)匿名内部类
适合创建那种只使用一次的类,创建匿名内部类的语法有些奇怪,创建时会立即创建一个该类的实例,这个类定义立即消失,匿名内部类不能重复使用,语法如下:

new 实现接口()| 父类构造器(实参列表)
{
	//实体部分

4)静态内部类
用static修饰的内部类,可以不依赖外部类创建实例。。非静态内部类不能有静态成员

参照<Java 内部类详解>

11.Java 是值传递还是引用传递?

  • 值传递是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量。
  • 引用传递一般是对于对象型变量而言的,传递的是该对象地址的一个副本, 并不是原对象本身 。
    一般认为,Java 内的传递都是值传递.,Java 中实例对象的传递是引用传递,Java 是值传递的!

12.JDK 中常用的包有哪些?

答:java.lang、java.util、java.io、java.net、java.sql。

13.Integer 的缓存机制

看下面例子:

public class CompareExample {
	public static void main(String[] args) {
		
		Integer num1 = new Integer(100);
		Integer num2 = new Integer(100);
		System.out.println("num1==num2 " + (num1 == num2));
		
		Integer num3 = 100;
		Integer num4 = 100;
		System.out.println("num3==num4 " + (num3 == num4));
		
		Integer num5 = 128;
		Integer num6 = 128;
		System.out.println("num5==num6 " + (num5 == num6));
		
		Integer num7 = 100;
		Integer num8 = new Integer(100);
		System.out.println("num7==num8 " + (num7 == num8));
		
		int num9 = 100;
		Integer num10 = new Integer(100);
		Integer num11 = 100;
		System.out.println("num9==num10 " + (num9 == num10));
		System.out.println("num9==num11 " + (num9 == num11));
	}
}
结果:

num1==num2 false
num3==num4 true
num5==num6 false
num7==num8 false
num9==num10 true
num9==num11 true
  • num1==num2 false

这个上文解释过了,num1和num2的内存地址不一样,==的左右操作数如果是对象的话,那么比较的是引用的地址,new产生的对象一定是新的内存地址,所以,这里和Integer的缓存机制无关的,最终的结果便是false

  • num3==num4 true

这里是true,num3和num4的初始化方式,是直接将数字赋值,这种方式,在初始化的时候,等价与下面的代码:
Integer num3 = Integer.valueOf(100);
这里便涉及到了Integer的缓存机制问题, Integer是对小数据(-128到127)是有缓存的,在jvm初始化的时候,数据-128到127之间的数字便被缓存到了本地内存中,这样,如果初始化-128127之间的数字,便会直接从内存中取出,而不需要再新建一个对象(后面会分析valueOf的代码和缓存的一点事情),所以,100这个数字再-128127之间,那么num3和num4实际上是引用的是一个内存地址,那么自然就是true了。

  • num5==num6 false

同上解析,128不在-128~127之间了,所以会使用new新建个对象,那么num5和num6的内存地址就不一样了,结果就是false

  • num7==num8 false

这个和第一个的解释基本一致,因为num8是new出来的,所以使用的内存地址和num7不一致,结果为false

  • num9==num10 true

这个就比较好玩了,这个和上面的那个唯一的区别在于num9的类型是int而num7的类型是Integer,那么为啥这里是true呢?
Integer是int的包装类,在和int做比较的时候,会自动拆箱成int数值类型,所以,这里便变成了数字(int)的比较,所以100肯定等于100啦

  • num9==num11 true

解析同上(不需要关注到底是否是new出来,因为最终都要拆箱,最终都要将比较变成基本数据类型的比较

参照Integer的缓存机制

14.下述两种方法分别创建了几个 Sring 对象?

// 第一种:直接赋一个字面量
String str1 = "ABCD";
// 第二种:通过构造器创建
String str2 = new String("ABCD");

解析:考察的是对 String 对象和 JVM 内存划分的知识。

答:String str1 = “ABCD”;最多创建一个String对象,最少不创建String对象.如果常量池中,存在”ABCD”,那么str1直接引用,此时不创建String对象.否则,先在常量池先创建”ABCD”内存空间,再引用.

String str2 = new String(“ABCD”);最多创建两个String对象,至少创建一个String对象。new关键字绝对会在堆空间创建一块新的内存区域,所以至少创建一个String对象。
在这里插入图片描述
当执行第一句话的时候,会在常量池中添加一个新的ABCD字符,str1指向常量池的ABCD

当执行第二句话的时候,因为有new操作符,所以会在堆空间新开辟一块空间用来存储新的String对象,因为此时常量池中已经有了ABCD字符,所以堆中的String对象指向常量池中的ABCD,而str2则指向堆空间中的String对象。

String 对象是一个特殊的存在,需要注意的知识点也比较多,这里给一个之前写的 String 详解的文章链接:传送门 其中包含的问题大概有:1)“+” 怎么连接字符串;2)字符串的比较;3)StringBuilder/StringBuffer/String 的区别;

15.==和equals

== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals 默认情况下是引用比较,只是很多类重新了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。
equals是Object类的方法。

16.String 属于基本数据类型吗?

String 不属于基本数据类型,基础类型有 8 种:byte、boolean、char、short、int、float、long、double,而 String 属于对象。

扩展:对于数值类型的基本类型的取值范围,我们无需强制去记忆,因为它们的值都已经以常量的形式定义在对应的包装类中了
在这里插入图片描述

17.java 中的 Math.round(-1.5) 等于多少?

四舍五入,Math.round(-1.5)=-1 ;Math.round(1.5)=-2

扩展:
Math类是一个很有用的数学帮助类,使用也非常简单,这个类比较特殊,首先他和String类一样都是用final修饰,所以不能有子类,还有就是它的构造方法是私有的,也就是我们不能通过new的方法在其它类中构造Math对象,那么我们怎样调用它的方法,原来它的所有的方法都是静态方法,也就是可以直接使用类名就可以访问方法了。

Math.floor(-10.1) 向下取整 ,等于-11
Math.ceil(-10.1) 向上取整,等于-10
Math.abs(-10.1) 取绝对值,等于10.1

static double pow(double a, double b)
返回第一个参数的第二个参数次幂的值。
static double random()
返回带正号的 double 值,大于或等于 0.0,小于 1.0。
static double sqrt(double a)
返回正确舍入的 double 值的正平方根。
static double pow(double a, double b)
返回第一个参数的第二个参数次幂的值。

18.java 中操作字符串都有哪些类?它们之间有什么区别?

操作字符串的类有:String、StringBuffer、StringBuilder。

String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。

StringBuffer 线性安全,StringBuilder 非线性安全,StringBuffer 性能比StringBuilder 低。(String也是线性安全的)
在经常改变字符串内容的情况下最好不要使用 String,在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。

补充:它们之间的转换
在这里插入图片描述
常用方法

17.什么是自动拆箱和自动装箱

在这里插入图片描述
在这里插入图片描述

19.i++ 与 ++i 到底有什么不同?

i++ 即后加加,原理是:先自增,然后返回自增之前的值
++i 即前加加,原理是:先自增,然后返回自增后的值
最通俗易懂的i++和++i详解

20.Java 对象初始化顺序?

父类静态成员(包括变量和方法、代码块,按代码中的顺序初始化)
子类静态成员(包括变量和方法、代码块,按代码中的顺序初始化)
父类成员变量
父类非静态代码块
父类构造方法
子类成员变量
子类非静态代码块
子类构造方法

参照<Java之创建对象初始化顺序>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值