Java基础面试题

来源:互联网 发布:电子技术仿真软件 编辑:程序博客网 时间:2024/06/07 06:18

1.输出下列代码结果

class A {static {System.out.println("1");}public A() {System.out.println("2");}}class B extends A {static {System.out.println("a");}public B() {System.out.println("b");}}public class HelloWorld {public static void main(String[] args) {A ab = new B();ab = new B();}}

分析:1.static优先于 构造器

             2.父类优先于子类

             3.静态快只执行一次


2.请用一段代码实现取得当前时间、将时间转换为可定义样式的字符串的函数。

public class HelloWorld {public static void main(String[] args) {System.out.println(getStringTime("HH:mm:ss"));}public static String getStringTime(String format) {Date nowday = new Date();long nowTime = nowday.getTime();SimpleDateFormat sdf = new SimpleDateFormat(format);return sdf.format(nowTime);}}


3.重载和重写的区别

重载:发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。
重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类;如果父类方法访问修饰符为private则子类中就不是重写。

4.构造器Constructor是否可被override

构造器不能被重写,不能用static修饰构造器,只能用public
private protected这三个权限修饰符,且不能有返回语句。

5.访问控制符public,protected,private,以及默认的区别

private只有在本类中才能访问;
public在任何地方都能访问;
protected在同包内的类及包外的子类能访问;
默认不写在同包内能访问。
6是否可以继承String类#
String类是final类故不可以继承,一切由final修饰过的都不能继承。

10.自动装箱与拆箱

装箱:将基本类型用它们对应的引用类型包装起来;
拆箱:将包装类型转换为基本数据类型;
Java使用自动装箱和拆箱机制,节省了常用数值的内存开销和创建对象的开销,提高了效率,由编译器来完成,编译器会在编译期根据语法决定是否进行装箱和拆箱动作。

21.HashMap的工作原理是什么?

HashMap内部是通过一个数组实现的,只是这个数组比较特殊,数组里存储的元素是一个Entry实体(jdk 8为Node),这个Entry实体主要包含key、value以及一个指向自身的next指针。HashMap是基于hashing实现的,当我们进行put操作时,根据传递的key值得到它的hashcode,然后再用这个hashcode与数组的长度进行模运算,得到一个int值,就是Entry要存储在数组的位置(下标);当通过get方法获取指定key的值时,会根据这个key算出它的hash值(数组下标),根据这个hash值获取数组下标对应的Entry,然后判断Entry里的key,hash值或者通过equals()比较是否与要查找的相同,如果相同,返回value,否则的话,遍历该链表(有可能就只有一个Entry,此时直接返回null),直到找到为止,否则返回null。

HashMap之所以在每个数组元素存储的是一个链表,是为了解决hash冲突问题,当两个对象的hash值相等时,那么一个位置肯定是放不下两个值的,于是hashmap采用链表来解决这种冲突,hash值相等的两个元素会形成一个链表。

 

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);其中有隐含的强制类型转换。

public class Test03 {
 
    publicstaticvoidmain(String[] args) {
        Integer f1 =100, f2 =100, f3 = 150, f4 =150;
 
        System.out.println(f1 == f2);
        System.out.println(f3 == f4);
    }
}

true false

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

答:不对,如果两个对象x和y满足x.equals(y) == true,它们的哈希码(hash code)应当相同。Java对于eqauls方法和hashCode方法是这样规定的:(1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;(2)如果两个对象的hashCode相同,它们并不一定相同。当然,你未必要按照要求去做,但是如果你违背了上述原则就会发现在使用容器时,相同的对象可以出现在Set集合中,同时增加新元素的效率会大大下降(对于使用哈希存储的系统,如果哈希码频繁的冲突将会造成存取性能急剧下降)。

21、描述一下JVM加载class文件的原理机制?
答:JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。
由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。当Java程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的Class对象。加载完成后,Class对象还不完整,所以此时的类还不可用。当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。最后JVM对类进行初始化,包括:1)如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;2)如果类中存在初始化语句,就依次执行这些初始化语句。
类的加载是由类加载器完成的,类加载器包括:根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子类)。从Java 2(JDK 1.2)开始,类加载过程采取了父亲委托机制(PDM)。PDM更好的保证了Java平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其他的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。JVM不会向Java程序提供对Bootstrap的引用。下面是关于几个类加载器的说明:

  • Bootstrap:一般用本地代码实现,负责加载JVM基础核心类库(rt.jar);
  • Extension:从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap;
  • System:又叫应用类加载器,其父类是Extension。它是应用最广泛的类加载器。它从环境变量classpath或者系统属性java.class.path所指定的目录中记载类,是用户自定义加载器的默认父加载器。

5、try、catch、finally执行顺序问题


    下面函数将返回?
1
2
3
4
5
6
7
8
9
publicstaticintfunc (){
    try{
        return1;
    }catch(Exception e){
        return2;
    }finally{
        return3;
    }
}
A、1    B、2    C、3     D、编译错误

正确答案:C
(1)try catch中只要有finally语句都要执行(有特例:如果try 或 catch 里面有 exit(0)就不会执行finally了);
(2)finally语句在try或catch中的return语句执行之后返回之前执行,且finally里的修改语句不能影响try或catch中 return已经确定的返回值;
        若finally里也有return语句则覆盖try或catch中的return语句直接返回;
 (3)在遵守第(2)条return的情况下,执行顺序是:try-->catch(如果有异常的话)-->finally


7、关于null对象、static变量和方法

有关下述Java代码描述正确的选项是____。
1
2
3
4
5
6
7
8
publicclassTestClass {
   privatestaticvoidtestMethod(){
        System.out.println("testMethod");
   }
   publicstaticvoidmain(String[] args) {
        ((TestClass)null).testMethod();
   }
}
        A、编译不通过
        B、编译通过,运行异常,报NullPointerException
        C、编译通过,运行异常,报IllegalArgumentException
        D、编译通过,运行异常,报NoSuchMethodException
        E、编译通过,运行异常,报Exception
        F、运行正常,输出testMethod

正确答案:F

    静态方法是属于类的,静态方法在对象实例创建前就已经存在了,它的使用不依赖于对象是否被创建。当我们通过类的实例来调用时,最后实际上还是将对象实例转换成了类去掉用该静态方法,所以这里的null只是迷惑大家的跟它没有什么关系。
    这里 ((TestClass)null).testMethod();也可以写成TestClass t = null; t.testMethod();同样可以正确输出。null可以被强制转换成任意类型对象,虽然这个时候t被赋为了空,但这个“空对象”也是属于TestClass的,那么这个“空对象”也就可以去堆上的静态方法区调用testMethod()方法了。
    如果这里testMethod把static去掉,该testMethod方法就变成了实例对象的方法了。这时,可以编译通过,但是会报空指针。

同理,对于static变量也是一样的。比如TestClass 中有如下变量:private static String str = "abc"; 我们通过TestClass t = null; System.out.println(t.str);同样可以正确输出。


9、关于内部类

往OuterClass类的代码段中插入内部类声明, 哪一个是错误的:
1
2
3
4
public class OuterClass{
    private float f=1.0f;
    //插入代码到这里
}
A、class InnerClass{public static float func(){return f;}}
B、abstract class InnerClass{public abstract float func(){}}
C、static class InnerClass{protected static float func(){return f;}}
D、public class InnerClass{ static float func(){return f;}}
正确答案:ABCD
静态的内部类才可以定义static方法,排除AD;
B抽象方法中不能有方法体;
C,静态方法不能够引用非静态变量。

10、Final修饰符、volatile修饰符


Final修饰符,用来修饰类、方法和变量,final修饰的类不能够被继承,修饰的方法可以被继承,重载,但是不能被子类重写(即重新定义)

(1)final变量:
被声明为final的对象引用不能指向不同的对象。但是final对象里的数据可以被改变。也就是说final对象的引用不能改变,但是里面的值可以改变。比如:
        final Person p = new Person();
        p.name = "aaa";
        p.name = "bbb";
但是,如果是final String str = "aaa";     str = "bbb";//错误编译不能通过,因为此时str的引用已经改变了!

(2)final修饰方法

Final修饰的方法可以被子类继承,但是不能被子类修改(重写)。

声明final方法的主要目的是防止该方法的内容被修改。


volatile修饰符,Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。一个volatile对象引用可能是null。



1、String的split(String regex)方法参数注意点

使用这个方法时,当我们直接以“.”为参数时,是会出错的,如:
[java] view plain copy
  1. String str = "12.03";  
  2. String[] res = str.spilt(".");    //出错!!!  
此时,我们得到的res是为空的(不是null),即str = [];
因为String的split(String regex)根据给定的正则表达式的匹配来拆分此字符串,而"."是正则表达式中的关键字没有经过转义split会把它当作一个正则表达式来处理的需要写成str.split("\\.")进行转义处理。

原创粉丝点击