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

一、关于null的一道小题 

先开开胃,一道非常有意思的笔试题。题目例如以下: 

以下这段代码能正确运行吗?假设能。输出什么?

public class NULL {
public static void haha(){
System.out.println("haha");
}
public static void main(String[] args) {
((NULL)null).haha();
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

答案是能正确执行!大家看出来答案用了多久?相信大家都比我强。我第一次看到这个表达式。脑子一片蒙蔽,后来细致分析代码,大写的NULL是类名,括号是对null做类型强转。然后调用NULL类的静态方法。 

输出为:

haha

由于null值能够强制转换为不论什么java类类型。比如(String)null也是合法的。但null强制转换后是无效对象,其返回值还是为null。而static方法的调用是和类名绑定的,不借助对象进行訪问,所以能正确输出。反过来,没有static修饰就仅仅能用对象进行訪问。使用null调用对象肯定会报空指针错了。

这里和C++非常类似。

很多其它null相关知识可參看博客深入理解Javakeywordnull

二、有关类载入机制的 静态块、块、构造方法 运行顺序问题 

非常经典、非常基础的问题。题目例如以下:以下这段代码输出什么?

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();
   } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

直接看输出结果:

static A 

static B 

I’m A class 

HelloA 

I’m B class 

HelloB

可见其运行顺序为: 

1、父类静态块 

2、子类静态块 

3、父类块 

4、父类构造器 

5、子类块 

6、子类构造器

关于对于静态块,仅仅能出如今类中,不能出如今不论什么方法中,且能够写在类中的任何位置(除了方法中),运行顺序与代码位置顺序一致!

假设想要深入当中原理。则须要了解static与Java的类载入机制。推荐海子的博客Java中statickeyword解析。推荐一本书《深入理解Java虚拟机》,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);
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

执行结果:

SSClass 

SuperClass init! 

123

答对了么? 

或许有人会疑问:为什么没有输出SubClass init。

ok~解释一下:对于静态字段。仅仅有直接定义这个字段的类才会被初始化。因此通过其子类来引用父类中定义的静态字段。仅仅会触发父类的初始化而不会触发子类的初始化。 

上面就牵涉到了虚拟机类载入机制。假设有兴趣。能够继续看下去。

三、Java參数传递机制问题

以下这段程序执行结果是什么?

public class Example {

    String str = new String("good");
char[] ch = { 'a', 'b', 'c' }; public static void main(String args[]) {
Example ex = new Example();
ex.change(ex.str, ex.ch);
System.out.print(ex.str + " and ");
System.out.print(ex.ch);
}
public void change(String str, char ch[]) {
str = "test ok";
ch[0] = 'g';
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

选项:

A、 good and abc 

B、 good and gbc 

C、 test ok and abc 

D、 test ok and gbc

答案为B,假设你选对了,那么你对Java中的參数传递机制已经了熟于胸了,有人可能以为Java中String和数组都是对象所以传递的肯定是对象引用类型,然后就会选D。事实上这是个非常大的误区:由于在java里没有引用传递,仅仅有值传递。

这个值指的是实參的地址的拷贝,得到这个拷贝地址后。你能够通过它改动这个地址的内容(引用不变),由于此时这个内容的地址和原地址是同一地址,可是你不能改变这个地址本身使其又一次引用其他的对象,也就是值传递,可能说的不是非常清楚,那么请看这个博文吧两段交换代码轻松理解Java參数传递机制,看了一定会明确!

四、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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

输出结果例如以下:

a==b:false 

a==c:true 

a==e:false 

c==e:true

解释: 

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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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

假设valueOf的数在这个范围之内的话。取到的就是同一个对象。用 == 来比較的话 结果就是true了; 

否则就是两个new Integer(i) 的赋值语句,也就是创建了两个Integer对象,自然用 == 来比較的话 结果就是false了。 

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

假设想深入了解Integer与自己主动装箱与拆箱知识,可參看博客Java包装类、自己主动装箱与拆箱知识总结 

刚刚这道题涉及了Java变量类型与内存机制的知识,能够參看博客Java内存机制学习笔记

五、Java字段的输出问题 

以下这段代码中成员变量与main()方法中定义的变量mainInt都未经过初始化。那么哪些变量能正确输出,输出什么,又有哪些输出语句不能通过编译呢?

public class Test {
//定义成员变量
public int testInt;
public float testFloat;
public boolean testBoolean;
public String testString; public static void main(String[] args){
/*
* 假设在main方法里定义一个变量,而不进行初始化就输出,是不能通过编译的! * int mainInt;
* System.out.println(mainInt);
*/
Test test = new Test();
System.out.println(test.testInt);
System.out.println(test.testFloat);
System.out.println(test.testString);
System.out.println(test.testBoolean); }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

而如上述凝视的部分中。在Java中假设在main方法里定义一个变量而不初始化。是不能通过编译的。 

而对于类成员变量。类载入器为我们做了初始化的工作。输出例如以下:



0.0 

null 

false

六、Java构造方法问题

例如以下题,“以下代码中,方法一与方法二中不运行不论什么代码运行”。这句话对不正确?

public class FatherClass {
//方法一
public FatherClass() {
}
} public class SonClass extends FatherClass {
//方法二
public SonClass() {
} public static void main(String[] args) {
new SonClass();
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

答:自然是不正确的。 

Java中对构造函数是不继承的,仅仅是调用(显式或隐式)。 

所以假设创建子类对象,那么首先调用父类的构造方法,怎样调用?系统会在子类构造方法中隐式的加入一句super();所以方法二处并非没有不论什么代码运行! 

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

这里贴出对Java构造方法的一些总结: 

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

总结2: 

假设父类没有显式编写不论什么构造方法,那么系统会自己主动加入一个无參的构造方法。假设父类显式编写了有參的构造方法,那么系统将不自己主动加入无參构造方法; 

则在创建子类对象时,不能通过编译,除非在子类构造方法代码体中第一行。必须是第一行显式调用父类有參构造函数!

例如以下: 

SonClass (){ 

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



假设不显式调用父类有參构造函数。系统会默认调用父类无參构造函数super(); 

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

七、关于抽象类与接口

abstract与interface非常重要,笔试时多以概念推断对错形式出题。在做一些总结!

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、抽象类能够包括构造器,用于抽象类的初始化,而接口不能够。

(未完待续)


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

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

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

  2. 【Java面试题系列】:Java基础知识常见面试题汇总 第一篇

    文中面试题从茫茫网海中精心筛选,如有错误,欢迎指正! 1.前言 ​ 参加过社招的同学都了解,进入一家公司面试开发岗位时,填写完个人信息后,一般都会让先做一份笔试题,然后公司会根据笔试题的回答结果,确定 ...

  3. Java基础知识常见面试题汇总第一篇

    [Java面试题系列]:Java基础知识常见面试题汇总 第一篇 文中面试题从茫茫网海中精心筛选,如有错误,欢迎指正! 1.前言 ​ 参加过社招的同学都了解,进入一家公司面试开发岗位时,填写完个人信息后 ...

  4. Java 基础常见知识点&面试题总结(中),2022 最新版!| JavaGuide

    你好,我是 Guide.秋招即将到来,我对 JavaGuide 的内容进行了重构完善,公众号同步一下最新更新,希望能够帮助你. 上篇:Java 基础常见知识点&面试题总结(上),2022 最新 ...

  5. Java 基础常见知识点&面试题总结(下),2022 最新版!

    你好,我是 Guide.秋招即将到来,我对 JavaGuide 的内容进行了重构完善,同步一下最新更新,希望能够帮助你. 前两篇: Java 基础常见知识点&面试题总结(上),2022 最新版 ...

  6. java基础知识 + 常见面试题

    准备校招面试之Java篇 一. Java SE 部分 1.1 Java基础 1. 请你解释Object若不重写hashCode()的话,hashCode()如何计算出来的? Object 的 hash ...

  7. 【Java面试题系列】:Java基础知识常见面试题汇总 第二篇

    文中面试题从茫茫网海中精心筛选,如有错误,欢迎指正! 第一篇链接:[Java面试题系列]:Java基础知识常见面试题汇总 第一篇 1.JDK,JRE,JVM三者之间的联系和区别 你是否考虑过我们写的x ...

  8. java基础常问面试题

    1.面向对象和面向过程的区别 面向过程 :面向过程性能比面向对象高. 因为类调用时需要实例化,开销比较大,比较消耗资源,所以当性能是最重要的考量因素的时候,比如单片机.嵌入式开发.Linux/Unix ...

  9. Java 基础常见知识点&面试题总结(上),2022 最新版!| JavaGuide

    你好,我是 Guide.秋招即将到来,我对 JavaGuide 的内容进行了重构完善,公众号同步一下最新更新,希望能够帮助你. 基础概念与常识 Java 语言有哪些特点? 简单易学: 面向对象(封装, ...

随机推荐

  1. python--MySQL多表查询

    一 介绍 我们在写项目的时候一般都会建一个数据库,数据库里面会存很多的表,不可能把所有的数据都放在一张表里,因为分表来存数据节省空间,数据的组织结构更清晰,解耦和程度更高,但是这些表本质上还不是一个整 ...

  2. SGU 149 树形DP Computer Network

    这道题搜了一晚上的题解,外加自己想了半个早上,终于想得很透彻了.于是打算好好写一写这题题解,而且这种做法比网上大多数题解要简单而且代码也比较简洁. 首先要把题读懂,把输入读懂,这实际上是一颗有向树.第 ...

  3. python基础学习笔记——迭代器

    我们之前一直在用可迭代对象进行操作,那么到底什么是可迭代对象.我们现在就来讨论讨论可迭代对象.首先我们先回顾下我们 熟知的可迭代对象有哪些: str  list   tuple  dic  set  ...

  4. 洛谷 P4961

    目录 题目 思路 Code 题目 戳 为了小埋A了这道题. 思路 读入原来的矩阵,将不是雷的格子更新为数字(数字就是该格子周围八格的雷的个数)将是雷的格子赋值为inf.然后就按照题目要求计算周围八格没 ...

  5. 关于Linux下使用expdp和impdp命令对Oracle数据库进行导入和导出操作

    说明:本次导入和导出采用expdp和impdp命令进行操作,这2个命令均需要在服务器端进行操作 http://www.cnblogs.com/huacw/p/3888807.html 一.    从O ...

  6. 03005_Tomcat

    1.Tomcat下载 (1)Tomcat解压版:链接:Tomcat解压版 密码:0iw0 : (2)源码:链接:源码 密码:3o43 . 2.Tomcat的目录结构 (1)bin:脚本目录   ①启动 ...

  7. java 罕见的依赖报错 jstat: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory

    java 都用了N长时间了,突然,意外地发现有一个依赖的so文件从来没找见过 # ldd /usr/bin/java linux-vdso.so.1 =>  (0x00007fffba76900 ...

  8. POJ 2157 Maze

    Maze Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 3183   Accepted: 996 Description A ...

  9. 也来“玩”Metro UI之磁贴(二)

    继昨天的“也来“玩”Metro UI之磁贴(一)”之后,还不过瘾,今天继续“玩”吧——今天把单选的功能加进来,还有磁贴的内容,还加了发光效果(CSS3,IE9+浏览器),当然,还是纯CSS,真的要感谢 ...

  10. 持续集成---jenkins环境部署

    一.环境准备 操作系统:linux系统,此时我安装的是centos6.5,操作步骤具体见博客<虚拟机安装centos6.5> 依赖软件:1.jdk, 2.tomcat9(需要安装两个,一个 ...