关于Java基础的一些笔试题总结

针对最近腾讯、京东、网易等公司的笔试,遇到一些有关Java基础的问题,在此通过一些例子总结一下,希望能通过这几道题发散,举一反三,借此打牢基础!自己总结,望提出宝贵意见!

一、最近笔试,经常会遇到一些“下面这段代码输出的结果是什么?是否编译出错?”类似的问题,代码如下:

public class Test {
	public int testInt;
	public float testFloat;
	public String testString;
	public boolean testBoolean;
	public A a;

	public static void main(String[] args){
		//如果在main方法里定义一个变量,而不进行初始化就输入,是不能通过编译的!
		//int testInt;
		//System.out.println(testInt);
		Test test = new Test();
		System.out.println(test.testInt);
		System.out.println(test.testFloat);
		System.out.println(test.testString);
		System.out.println(test.testBoolean);
		System.out.println(test.a);
	}
}

class A{}

那我们考虑能不能通过编译呢?答案是可以的,对于成员变量,类加载器为我们做了初始化的工作。输出如下:

而如上述代码中,如果在main方法里定义一个变量而不初始化,是不能通过编译的!

二、对于null

前两天看到一道很有意思的笔试题,题目如下:

下面这段代码能运行吗?

public class NULL {

    public static void haha(){
        System.out.println("haha");
    }
    public static void main(String[] args) {
        ((NULL)null).haha();
    }

}

答案是能运行,我第一次看到这个表达式,脑子一片蒙蔽,后来仔细分析,大写的NULL是类名,括号是类型转换,然后调用NULL类的静态方法。

输出为haha,因为null值可以强制转换为任何java类类型,(String)null也是合法的。但null强制转换后是无效对象,其返回值还是为null,而static方法的调用是和类名绑定的,不借助对象进行访问所以能正确输出。反过来,没有static修饰就只能用对象进行访问,使用null调用对象肯定会报空指针错了。这里和C++很类似。

更多null可参看博客深入理解Java关键字null

三、类加载时的静态块与构造方法执行顺序问题

很经典、很基础的问题,即使不懂其中机制,记住就足够了。题目如下:

class HelloA {

    public HelloA() {
        System.out.println("HelloA");
    }

    { System.out.println("I'm A class"); }

    static { System.out.println("static A"); }

}

public class HelloB extends HelloA {
    public HelloB() {
        System.out.println("HelloB");
    }

    { System.out.println("I'm B class"); }

    static { System.out.println("static B"); }

    public static void main(String[] args) {
     new HelloB();
   }

}

直接看输出结果:

static A
static B
I‘m A class
HelloA
I‘m B class
HelloB

可见其执行顺序为:

1、父类静态块

2、子类静态块

3、父类块

4、父类构造器

5、子类块

6、子类构造器

还有一点比较重要,对于静态块,只能出现在类中,不能出现在任何方法中,且可以写在类的任意位置,执行顺序与代码顺序一致!

如果想要深入其中原理,则需要了解Java的类加载机制与static,推荐一本书《深入理解Java虚拟机》,推荐海子的博客Java中的static关键字解析,ImportNew博文Java虚拟机类加载机制,其中有一段代码与上述问题类似,但更深入,题目如下:

下面这段代码输出什么?

public class SSClass
{
    static
    {
        System.out.println("SSClass");
    }
}
public class SuperClass extends SSClass
{
    static
    {
        System.out.println("SuperClass init!");
    }

    public static int value = 123;

    public SuperClass()
    {
        System.out.println("init SuperClass");
    }
}
public class SubClass extends SuperClass
{
    static
    {
        System.out.println("SubClass init");
    }

    static int a;

    public SubClass()
    {
        System.out.println("init SubClass");
    }
}
public class NotInitialization
{
    public static void main(String[] args)
    {
        System.out.println(SubClass.value);
    }
}

运行结果:

SSClass

SuperClass
init!

123

答案答对了么?

也许有人会疑问:为什么没有输出SubClass init。ok~解释一下:对于静态字段,只有直接定义这个字段的类才会被初始化,因此通过其子类来引用父类中定义的静态字段,只会触发父类的初始化而不会触发子类的初始化。

上面就牵涉到了虚拟机类加载机制。如果有兴趣,可以继续看下去。

四、包含继承关系的构造方法问题

如下题,方法一与方法二中不执行任何代码执行对不对?

public class FatherClass {
	//方法一
	public FatherClass() {
	}
}

public class SonClass extends FatherClass {
	//方法二
	public SonClass() {
	}

public static void main(String[] args) {
new SonClass();
	}
}

答:Java中对构造函数是不继承的,只是调用(显式或隐式);

所以如果创建子类对象(new SonClass()),那么首先调用父类的构造方法,如何调用?系统会在子类构造方法中隐式的添加一句super();所以方法二处并不是没有任何代码执行!

那么方法一处有代码执行吗?有人可能以为它是父类就不用执行代码了。但Java中,所有类都是Object的父类!方法一处仍然需要调用父类构造方法!

总结1:构造函数不能继承,只是调用而已。

如果父类没有无参构造函数,创建子类对象时,不能编译,除非在构造函数代码体中第一行,必须是第一行显式调用父类有参构造函数

如下:

SonClass (){

super(777);//显示调用父类有参构造函数

}

如果不显示调用父类有参构造函数,系统会默认调用父类无参构造函数super();

但是父类中没有无参构造函数,那它不是不能调用了。所以编译就无法通过了。

总结2:创建有参构造函数后,系统就不再有默认无参构造函数。

如果没有任何构造函数,系统会默认有一个无参构造函数。

五、Integer与int的‘==‘比较问题

public class Test {
	public static void main(String[] args) {

		Integer a = new Integer(1);
		Integer b = new Integer(1);
		int c=1;
		Integer e = 1;
		System.out.println("a==b:"+(a==b));
		System.out.println("a==c:"+(a==c));
		System.out.println("a==e:"+(a==e));
		System.out.println("c==e:"+(c==e));
	}
}

输出结果如下:

解释:

1、a与b是两个引用类型变量,他们的值是为两个对象在堆内存中的分配空间的首地址,存放在栈的局部变量表中。

new了两个对象,内存中存放位置一定不同,所以a和b也一定不同,故false。

2、c与d为值类型,其值就存放在栈中,与堆内存无关,所以引用类型a与值类型c比较,a自动拆箱为int,与c进行值比较,故true。

3、而Integer d = 1;这条语句比较特殊,它是调用Integer.valueOf(1)自动装箱进Integer对象d,但这里有个很关键的问题参看valueOf源码:

 public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
    return IntegerCache.cache[i + offset];
}
       return new Integer(i);
   }  

-128 ~ 127 这个范围内的数被Java缓存的 类似一个线程池或连接池之类的结构。

如果valueOf的数在这个范围之内的话,取到的就是同一个对象;

否则就是两个new Integer(i) 的赋值语句 就是创建了两个Integer对象.

自然用 == 来比较的话 结果就是false了。

4、两个值类型比较,自然是true!

如果想深入了解Integer与自动装箱与拆箱知识,可参看Java包装类、自动装箱与拆箱知识总结

六、关于抽象类与接口

abstract与interface很重要,笔试时必被问到,个人的一些总结,在此分享,具体参看Java抽象类与接口学习心得

1、抽象类

对于抽象类有“三必须”与“五不能”。

三必须(三种情况必须定义为抽象类):

a、一个类中直接定义了一个或多个抽象方法;

b、一个类继承了一个抽象父类,但没有实现父类中的抽象方法;

c、一个类实现了一个接口,但没有完全实现接口包含的抽象方法;

五不能:

a、抽象类不能被实例化(即抽象类不能被new);

b、abstract与final永远不能同时使用(final修饰的类不能被继承,修饰的方法不能被重写;而abstract修饰的类只能被继承才有意义,修饰的方法必须被重写才有意义);

c、abstract与static不能同时修饰方法(static修饰的方法属于类本身,如果抽象方法被static修饰,通过类调用该方法时会因为没有方法体而出错);

d、abstract与private不能同时使用(abstract修饰的方法必须重写才有意义,而private使访问权限受限);

e、abstract不能修饰变量(即没有抽象变量);

2、接口

接口是彻底化的抽象类。

需要注意的是:

a、一个接口可以有多个父接口,但接口只能继承接口,不能继承类;

b、接口里的方法全是抽象方法(public abstract);

c、接口里定义的字段(Field)只能是是常量(public static final);

3、抽象类与接口相似之处

a、抽象类与接口不能被实例化,只能被其他类继承或实现;

b、抽象类和接口都可以包含抽象方法,抽象类的继承类与接口的实现类都必须实现父类中的抽象方法;

4、抽象类与接口的主要区别

a、设计目的区别:抽象类体现的是一种模板式的设计,用户可以在这个基础上增加完善功能;而接口体现的是一种规范,用户只能且必须完成这个规范;

b、抽象类可以包含普通方法,而接口不可以;

c、Java中一个类只能有一个直接父类,但一个类可以实现多个接口,接口从某种程度上说弥补了Java单继承的不足;

d、抽象类可以包含构造器,用于抽象类的初始化,而接口不可以;

(未完待续)

时间: 2024-11-06 12:02:13

关于Java基础的一些笔试题总结的相关文章

有关Java基础的一些笔试题总结

针对最近腾讯.京东.网易等公司的笔试,遇到一些有关Java基础的问题,在此总结,希望能通过这几道经典问题题发散,举一反三,借此打牢基础!自己总结,望提出宝贵意见! 一.关于null的一道小题 先开开胃,一道很有意思的笔试题,题目如下: 下面这段代码能正确执行吗?如果能,输出什么? public class NULL { public static void haha(){ System.out.println("haha"); } public static void main(Str

Java开发工程师上机笔试题

网上看到3道比较好的Java开发工程师上机笔试题,没有答案这里把答案写出来,给大家参考. 1.编一个程序,输入10个整数,并放在数组中,先降序输出所有的数,再统计并输出其中正数.负数和零的个数 package cn.Pigzhu.test; import java.util.Scanner; /**  * 控制台输入10个数字,并输入正负和零的个数  * @author xiaoyezhu  *  */ public class test { public static void main(St

班上一个哥们java脑残的笔试题1,2,3,4等于12可以重复3分钟答出来

package com.hao947; public class hao947 { public static void main(String[] args) { int a = 1; int b = 2; int c = 3; int d = 4; int count = 0; for (int i = 0; i <= 12; i++) { for (int j = 0; j <= 6; j++) { for (int k = 0; k <= 4; k++) { for (int l

计算机网络基础知识(笔试题)

1.OSI(Open System Interconnect):开放系统互联,是一个七层的计算机网络模型,分别为:物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. TCP/IP(Transmission Control Protocol/Internet Protocol):传输控制协议/因特网互联协议,是一个四层的计算机网络模型,分别为:网络接口层.网络层.传输层和应用层.结合OSI和TCP/IP产生了一个五层结构,分别为:物理层.数据链路层.网络层.传输层和应用层.Interne

阿里巴巴java研发2015实习笔试题--生产者消费者并发线程安全

import java.util.ArrayList;import java.util.List;/** * 箱子最多装5个苹果.一个人往里放,一个人往外拿.苹果无限. * @author Administrator */public class test01 { public static void main(String[] args) { // 共享资源 Production pro = new Production(); Custom custom = new Custom(pro);

蛮考验基础的JS笔试题(有坑小心!)

1.  考察this 1 var length = 10 2 function fn(){ 3 alert(this.length) 4 } 5 var obj = { 6 length: 5, 7 method: function(fn) { 8 fn() // ? 9 arguments[0]() // ? 10 } 11 } 12 obj.method(fn) 这里的坑主要是arguments,我们知道取对象属于除了点操作符还可以用中括号,这里fn的scope是arguments,即fn内

【Java面试题系列】:Java基础知识面试题,看这一篇就够了

文中面试题从茫茫网海中精心筛选,如有错误,欢迎指正! 1.前言 参加过社招的同学都了解,进入一家公司面试开发岗位时,填写完个人信息后,一般都会让先做一份笔试题,然后公司会根据笔试题的回答结果,确定要不要继续此次面试,如果答的不好,有些公司可能会直接说"技术经理或者总监在忙,你先回去等通知吧",有些公司可能会继续面试,了解下你的项目经验等情况. 至少在工作的前5年甚至更久,面试一般不会跳过笔试题这个环节(大牛,个别公司除外),我自己也记不清自己面试过多少家公司,做过多少份面试题了,导致现

10月12日笔试题总结

10/12,昨天参加了一套c/c++基础知识的笔试题,题目不难却有些偏门,笔试中个人感觉有如下问题需要重视: 指针与引用指向的内存位置;变量调用之堆和栈.(关于堆和栈的知识) char c=134;printf("%d",c);printf("%u",c);(整数和字符型相互转换的问题) 位操作:位与&.异或^.非~和移位(<<.>>),位或|(考试中,被当成数理逻辑的合取算符来用了,很长时间不用位或,关键时刻掉链子): 二进制.十六

Android开发面试经——4.常见Java基础笔试题

关注finddreams博客:http://blog.csdn.net/finddreams/article/details/44403041 因为Androd使用Java语言来编程的,所以我们做Android开发全面的掌握Java基础是必须的.在面试的过程中,我们发现很多公司发的笔试题有很多知识点都是Java的,搞安卓久了,Java基础的一些知识点也都快忘了,今天就让我们来一起复习一些Java基础,希望能在面试中用到: 1.Overload和Override的区别.Overloaded的方法是