Java程序员面试题之JavaSE之基础篇

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java程序员面试题之JavaSE之基础篇相关的知识,希望对你有一定的参考价值。

一、JavaSE之基础篇

1、JavaSE基础之语法

######(1)、简述你对JVM,JRE,JDK的理解?
JVM:java虚拟机。是一个模拟的计算机,相当于真实存在的计算机(软件+硬件)。
JDK:是整个java的核心。程序员的产品。包括了java的运行环境、java的工具、java的基础类库。
JRE:运行环境。
拓展----JVM、JDK和JRE之间的关系:JDK包括JRE,JRE包括JVM
######(2)、一个".java"源文件中是否可以包括多个类(非内部类)?有什么限制?
一个".java"源文件中可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致。
一个".java"源文件中可以只有非public类,但是,如果只有一个非public类,此类可以跟文件名不同。
######(3)、Java有没有goto?
goto在java中作为保留字存在,现在在java中没有使用了。
######(4)、说说&和&&的区别 ?
1.&和&&都可以用作逻辑与的运算符,&&为短路与,&不是短路与。另外&可以做为整数的位运算符。
例1:对于if(str != null&& !str.equals(“”))表达式,当str为null时,后面的表达式不会执行,所以不会出现NullPointerException如果将&&改为&,则会抛出NullPointerException异常。
2.&&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式.
例2:If(x==33 & ++y>0) y会增长,if(x==33 && ++y>0)不会增长。
备注:这道题先说两者的共同点,再说出&&和&的特殊之处,并列举一些经典的例子。
######(5)、在JAVA中如何跳出当前的多重嵌套循环?

  1. Break + 标签
  2. 直接使用Break
  3. 使用方法的return

    例如下面代码片段:
  4. Break + 标签
    ok: for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
    System.out.println("i=" + i + ",j=" + j);
    if (j == 5)
    break ok;
    }
    }
  5. 直接使用Break
    int arr[][] ={{1,2,3},{4,5,6,7},{9}};
    boolean found = false;
    for(int i=0;i<arr.length&& !found;i++) {
    for(int j=0;j<arr[i].length;j++){
    System.out.println("i=" + i + ",j=" + j);
    if(arr[i][j] ==5) {
    found = true;
    break;
    }
    }
    }
  6. 使用方法的return
    private static int test() {
    int count = 0;
    for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
    count++;
    System.out.println("i=" + i + ",j=" + j);
    if (j == 5) {
    return count;
    }
    }
    }
    return 0;
    }
    ######(6)、switch语句能否作用在byte上,能否作用在long上,能否作用在String上?
    switch语句可以作用在byte, short, char, int, String, enum, 封装类对象。
    其它基本数据类型及引用数据类型都不能做为case的条件。
    ######(7)、short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
    对于short s1 = 1; s1 = s1 + 1;由于s1+1运算时会自动提升表达式的类型,所以结果是int型,再赋值给short类型s1时,编译器将报告需要强制转换类型的错误。
    对于short s1 = 1; s1 += 1;由于 +=是java语言规定的运算符,java编译器会对它进行特殊处理,因此可以正确编译。
    ######(8)、char型变量中能不能存贮一个中文汉字?为什么?
    char型变量中能存贮一个中文汉字,因为char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字。
    补充说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。
    ######(9)、用最有效率的方法算出2乘以8等於几?
    2 << 3 因为将一个数左移n位,就相当于乘以了2的n次方,那么,一个数乘以8只要将其左移3位即可,而位运算cpu直接支持的,效率最高,所以,2乘以8等於几的最效率的方法是2 << 3。
    ######(10)、使用final关键字修饰一个变量时,是引用变量不能变,还是引用的对象不能变?
    是引用变量不能变,引用变量所指向的对象中的内容是可以改变的,但是不能再去new新的对象。

    例1:如下面代码,编译就会出错
        final StringBuffer a=new StringBuffer("immutable");
        a=new StringBuffer("");
    
    例2:如下面代码,编译正确
        final StringBuffer a=new StringBuffer("immutable");
        a.append(“123”);

    ######(11)、"=="和equals方法有什么区别?
    他们的区别主要是在引用数据类型上面:
    1.==为比较两侧的对象是否同一对象,是用内存地址来比较的;
    2.equals是方法,默认是用内存地址比较,重写后,主要是用来比较两侧的对象的值是否相同,和equals方法中的实现有关;
    注意:==可以两侧都为null,但equals左侧的引用指向的对象不能空,否则会出现NullPointerException异常。
    ######(12)、静态变量和实例变量的区别?
    1.在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。
    2.在程序运行时的区别:
    实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。
    静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。
    总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
    ######(13)、是否可以从一个static方法内部发出对非static方法的调用?
    不可以。
    因为非static方法(实例方法)是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用。
    也就是说,当一个static方法被调用时,可能还没有创建任何实例对象,如果从一个static方法中发出对非static方法的调用,那个非static方法是关联到哪个对象上的呢?这个逻辑无法成立,所以,一个static方法内部发出对非static方法的调用。
    ######(14)、Integer与int的区别?
    1.int是java提供的8种原始数据类型之一,意思整型,占用4字节。
    2.Integer是java为int提供的封装类,是引用数据类型。
    3.int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况。例如,要想表达出没有参加考试和考试成绩为0的区别,则只能使用Integer。
    4.在JSP开发中,Integer的默认为null,所以用el表达式在文本框中显示时,值为空白字符串,而int默认的默认值为0,所以用el表达式在文本框中显示时,结果为0,所以,int不适合作为web层的表单数据的类型。
    5.在Hibernate中,如果将OID定义为Integer类型,那么Hibernate就可以根据其值是否为null而判断一个对象是否是临时的,如果将OID定义为了int类型,还需要在hbm映射文件中设置其unsaved-value属性为0。
    6.另外,Integer提供了多个与整数相关的操作方法,例如,将一个字符串转换成整数,Integer中还定义了表示整数的最大值和最小值的常量。
    ######(15)、Math.round(11.5)等于多少? Math.round(-11.5)等于多少?
    Math.round(11.5)的结果为12,Math.round(-11.5)的结果为-11。
    解析:Math类中提供了三个与取整有关的方法:ceil、floor、round,这些方法的作用与它们的英文名称的含义相对应。
    例如:ceil的英文意义是天花板,该方法就表示向上取整,Math.ceil(11.3)的结果为12,Math.ceil(-11.3)的结果是-11;floor的英文意义是地板,该方法就表示向下取整,Math.ceil(11.6)的结果11,Math.ceil(-11.6)的结果是-12。
    ######(16)、下面的代码有什么不妥之处?

  7. if(username.equals(“zxx”){......}
    username可能为null,会报空指针错误;改为"zxx".equals(username)
  8. int x = 1;
    return x==1?true:false; 这个改成return x==1;就可以!
    ######(17)、请说出作用域public,private,protected,以及不写时的区别?
    这四个作用域的可见范围如下表所示。(说明:如果在修饰的元素上面没有写任何访问修饰符,则表示friendly/default。)
    技术分享图片
    ######(18)、Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?
    1.Overload是重载的意思,Override是重写的意思。
    2.Overload和Override有共同之处,两个方法的方法名都必须相同,如果不同,既不构成Overload,也不构成Override。
    3.Override必须发生在父子类之间,Overload可以不在父子类之间。
    4.Override(重写)的特点:
    a)参数列表完全相同:个数相同、类型相同、顺序相同;
    b)子类的返回值不能比父类的返回值范围大;
    c)子类方法抛出的异常不能比父类方法抛出的异常范围大;
    d)修饰符只能为public、protected、friendly,不能为private;
    e)父子类方法不能使用static修饰。
    4.重载发生在同一个类或父子类之间,重载中参数列表至少满足个数不同、类型不同、顺序不同中的一个条件,不包含父子类之间的static方法。
    ######(19)、构造器Constructor是否可被override(即构造函数是否可被重写)?
    不能。
    因为构造器Constructor不能被继承,因此不能Override(重写)。但构造器Constructor可以被Overload(重载)。
    ######(20)、接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)? 抽象类中是否可以有静态的main方法? 抽象类是否可有以内部类? 接口是否可以有内部类?
    接口可以继承接口;
    抽象类可以实现(implements)接口;
    抽象类可以继承具体类;
    抽象类中可以有静态的main方法;
    抽象类可有以内部类;
    接口可以有内部类,但必须是static内部类,但不一定是final的。
    (注意:抽象类与普通类的唯一区别就是不能创建实例对象和允许有abstract方法。)
    ######(21)、写clone()方法时,通常都有一行代码(不是必须有),是什么?
    super.clone();
    因为clone有缺省行为,首先要把类中的成员复制到位,然后才是复制自己的成员。
    ######(22)、面向对象的特征有哪些方面?
  9. 封装,隐藏内部实现,只暴露公共行为;
  10. 继承,提高代码的重用性;
  11. 多态,体现现实生活中相似对象的差异性;
  12. 抽象,抽取现实世界中相似对象的共同点。
    ######(23)、满足多态的必要条件有哪些?
  13. 要有继承;
  14. 要有重写;
  15. 父类引用指向子类对象;
    ######(24)、java中实现多态的机制是什么?
    通过继承父类或实现接口。
    1.继承指子类继承父类的所有属性、方法、内部类。对于属性而言,如果子类的属性名和父类的属性名相同,则子类会把父类的属性隐藏。属性根据引用来调用,方法根据对象来调用;Java中只有单继承,一个子类只能直接继承一个父类。
    2.实现接口指某类可以实现接口中的部分或所有方法,并能继承接口中的所有的属性和内部类。接口中的属性都为public static final类型,方法都为public类型,内部类都为public static类型。接口可以继承多个接口,实现类可以实现多个接口。
    ######(25)、abstract class和interface有什么区别?
    含有abstract修饰符的class即为抽象类,abstract类不能创建的实例对象。含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必是抽象的。abstract class类中定义抽象方法必须在具体(Concrete)子类中实现,所以,不能有抽象构造方法或抽象静态方法。如果的子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为abstract类型。
    接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。
    下面比较一下两者的语法区别:
    1. 抽象类可以有构造方法,接口中不能有构造方法。
    2. 抽象类中可以有普通成员变量,接口中没有普通成员变量
    3. 抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
    4. 抽象类中的抽象方法的访问类型可以是public,protected和默认类型,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
    5. 抽象类中可以包含静态方法,接口中不能包含静态方法
    6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
    7. 一个类可以实现多个接口,但只能继承一个抽象类。
      下面接着再说说两者在应用上的区别:
      1.接口更多的是在系统架构设计方法发挥作用,主要用于定义模块之间的通信契约;
      2.而抽象类在代码实现方面发挥作用,可以实现代码的重用。
      ######(26)、25、抽象(abstract)的方法(method)是否可以同时是静态(static)的? 是否可以同时是本地化(native)的? 是否可以同时是同步(synchronized)的? 是否可以同时是最终(final)的?
      1.抽象(abstract)的方法(method)不可以是静态(static)的,因为抽象的方法是要被子类实现的,而static与子类扯不上关系!
      2.本地化(native)方法表示该方法要用另外一种依赖平台的编程语言实现的,不存在着被子类实现的问题,所以,它也不能是抽象的,不能与abstract混用。
      3.同步(synchronized)和抽象(abstract)合用的问题不能共用,抽象(abstract)方法只能存在于抽象类或接口中,它不能直接产生对象,而默认同步(synchronized)方法对当前对象加锁,没有对象是不能加锁。另外synchronized不能被继承,子类继承时,需要另加修改符。
      4.最终(final)方法和抽象(abstract)不能共用,因为final是不能被子类重写的,而抽象方法必须被某级子类重写。
      ######(27)、什么是内部类?静态内部类和内部类有什么不同?
      内部类就是在一个类的内部定义的类。
      静态内部类和内部类的区别:
    8. 静态内部类需要使用static修饰,而普通内部类不能使用static修饰;
    9. 静态内部类只能定义在和属性同级,普通内部类可以定义在除参数位置以外的任意位置;
    10. 静态内部类必需有名称,而普通内部类可以是匿名的;
    11. 静态内部类没有this引用,只此只能访问外部类的静态成员,而普通内部类可以访问外部类的全部成员;
    12. 静态内部类访问外部类的同名函数时,使用“外部类名.方法名”即可,而普通内部类需要使用“外部类名.this.外部方法”;
    13. 静态内部类可以定义静态方法,而普通内部类不能定义静态方法,但能定义简单数据类型的静态属性,不能定义引用类型的静态属性。
      ######(28)、内部类可以引用它的包含类的成员吗?有没有什么限制?
  16. 如果内部类为静态内部类,只能调用外部类的静态成员;如果有重名成员,需要用“外部类名.成员名”访问;不能调用外部类的对象成员。
  17. 如果内部类为非静态内部类,则可以调用外部类的所有成员;如果有重名成员,需要使用“外部类名.this.成员名”。
    ######(29)、匿名内部类是否可以继承其它类? 是否可以实现接口?
    可以继承其他类或者实现其他接口。不仅是可以,而且是必须的!
    ######(30)、super.getClass()方法和this.getClass()方法返回对象是否相同?
    返回的Class对象是同一对象,都是子类的对象。
    ######(31)、String是最基本的数据类型吗?
    String是引用数据类型。
    基本数据类型包括byte、int、char、long、float、double、boolean和short。
    ######(32)、String s = "Hello";s = s + " world!";这两行代码执行后,原始的String对象中的内容到底变了没有?
    没有。
    因为String被设计成不可变(immutable)的类,所以它的所有对象都是不可变对象。
    ######(33)、是否可以继承String类?
    String类是final类故不可以继承。
    ######(34)、String s = new String("xyz");创建了几个String Object?二者之间有什么区别?
    两个对象。一个是"xyz",是缓冲区对象。另一个是new出来的String对象。这两个对象的值相同,但不是同一个对象。
    ######(35)、新建对象有几种方式?
  18. 使用new关键字
  19. 使用反射,调用newInstance方法
  20. 使用clone方法
  21. 使用序列化与反序列化
  22. 动态代理(Proxy类和CGLIB)
    ######(36)、String和StringBuffer的区别?
    相同之处:这两个类都实现了CharSequence接口。
    不同之处:

    1. 类型不同,因为不是一个类,也没有继承关系,做参数时不能共用
    2. String对象是不可变对象,不能修改值。而StringBuffer是可变对象,能修改值。
    3. 拼接字符串时,String会产生新对象,而StringBuffer只是增加新字符,不产生新对象,因此效率高。
    4. String覆盖了equals方法和hashCode方法,而StringBuffer没有覆盖equals方法和hashCode方法,所以,将StringBuffer对象存储进Java集合类中时会出现问题。
      ######(37)、StringBuffer和StringBuilder的区别?
      相同之处:这两类都是可变长的字符串存储类,都实现了CharSequence接口。
      不同之处:
    5. 类型不同,因为不是一个类,也没有继承关系,做参数时不能共用。
    6. StringBuffer为线程安全类,StringBuilder为线程非安全类。
    7. StringBuffer性能低,StringBuilder性能高,如果在局部优先使用StringBuilder。
    8. JDK在1.5之前,字符串相加使用StringBuffer对象,在1.5之后使用StringBuilder对象。
      ######(38)、如何把一段逗号分割的字符串转换成一个数组?
      1.用正则表达式,核心代码片段为:String [] result = orgStr.split(“,”, -1);
      2.用 StingTokenizer
      3.最笨的办法,用String.indexOf();

      代码片段如下:
      2.用 StingTokenizer:
      StringTokenizer tokener = new StringTokenizer(s, ",");
      String[] result = new String[tokener.countTokens()];
      Integer i = 0;
      while (tokener.hasMoreTokens()) {
      result[i++] = tokener.nextToken();
      }
      3.最笨的办法,用String.indexOf()
      int index = -1;
      int oldIndex = 0;
      List<String> ss = new ArrayList<String>();
      while ((index = s.indexOf(‘,‘, index + 1)) != -1) {
      ss.add(s.substring(oldIndex, index));
      oldIndex = index + 1;
      }
      if (s.charAt(s.length() - 1) == ‘,‘) {
      ss.add("");
      }
      String[] array = ss.toArray(new String[ss.size()]);
      System.out.println(Arrays.toString(array));
      ######(39)、数组有没有length()这个方法? String有没有length()这个方法? JS的数组有没有length()方法? JS的字符串有没有length()方法?
      数组没有length()这个方法,有length的属性。String有有length()这个方法。JS中只有length属性,没有length方法。
      ######(40)、String s="a"+"b"+"c"+"d"这条语句一共创建了多少个对象?
      产生了一个对象,即"abcd"。
      分析如下:
      String s1 = "a";
      String s2 = s1 + "b";
      String s3 = "a" + "b";
      System.out.println(s2 == "ab"); // false
      System.out.println(s3 == "ab"); // true
      String s = "a" + "b" + "c" + "d";
      System.out.println(s == "abcd"); // true s被优化为”abcd”

######(41)、能不能自己写个类,也叫java.lang.String?
可以。
但在应用的时候,需要用自己的类加载器去加载,
否则,系统的类加载器永远只是去加载rt.jar包中的那个java.lang.String。
######(42)、try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后?
也许你的答案是在return之前,但往更细地说,应该是在return中间执行。
请看下面程序代码的运行结果:
public class Test {
public static void main(String[] args) {
System.out.println(test());
}

        static int test() {
           int x = 1;
           try {
               return x;
           }
           finally {
               ++x;
           }
        }
    }
    ---------执行结果 ---------
    1 

    运行结果是1,为什么呢?主函数调用子函数并得到结果的过程,好比主函数准备一个空罐子,当子函数要返回结果时,先把结果放在罐子里,然后再将程序逻辑返回到主函数。所谓返回,就是子函数说,我不运行了,你主函数继续运行吧,这没什么结果可言,而结果已经被放进罐子里了。

######(43)、final, finally, finalize的区别?
1.final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
注意:内部类要访问局部变量,局部变量必须定义成final类型。
如下面代码:

            final int[] number = { 20 };
            new Thread() {
                @Override
                public void run() {
                    for (int k = 0; k < 20; k++) {
                        number[0]++;
                    }
                }
            }.start();
            Thread.sleep(10);
            System.out.println(number[0]);
        2.finally是异常处理语句结构的一部分,表示总是执行,用来释放资源。
        3.finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证此方法总被调用。

以上是关于Java程序员面试题之JavaSE之基础篇的主要内容,如果未能解决你的问题,请参考以下文章

前端面试题之代码输出篇

前端面试题之手写promise

Java面试题之高级篇研读

JavaScript面试题之代码篇

经典Python面试题之基础80问 Python开发

好程序员Java学习路线分享Java面试题之加载机制