Java开发面试经验分享:手写HelloWorld类的重要性与技巧
大家好,我叫老田。今天要跟大家分享的是群里朋友的面试经历。

这位小伙伴入行是从事Java开发的,入行还不到三年。最近,他私下告诉我,他在队里没有存在感,决定找一头骑在马背上的毛驴。
真的,如果你面试次数多了,你自然会遇到一些奇怪的面试官(他们不按规矩办事)。
背景
他遇到了一位面试官,面试官认为这很奇怪。面试官让他当场手写一个HelloWorld类,输出“Hello World!”。幸运的是,这位朋友留言了,默默地写下了。所以这一步并没有给他带来什么麻烦。
事实上,地球人都知道编程是从HelloWorld开始的。
这种情况下,请自行编写一个java入门程序HelloWorld。
希望大家填写真实情况,让我们看看有多少人不会手写。
是的,我们刚开始学习Java的时候也是这样。我们编写的第一个程序是HelloWorld:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
一开始老师还教我们使用javac来编译java文件,编译成.class文件,然后使用java命令运行,最后输出“Hello World”。
这道面试题我也问过很多工作不到三年的朋友,发现手写没那么简单(有的人忘记写参数,有的人数组类型参数没有写错,而有些人System.out.println()就不写了)。
如果你认为这很容易!并且你可以一口气写出HeeloWorld类创建的代码,那么恭喜你,你已经通过了第一关。
兴奋还在继续,面试官对这个HelloWorld进行了详细的询问。
问题
1.为什么是静态方法?
2.为什么方法没有返回参数?
3.为什么该方法命名为main?
4.为什么方法参数是数组?
5.你熟悉System类吗? System类有哪些常用方法?
其实问题远不止5个,比如:
您可以将公共更改为受保护或私有吗?
类中的main方法可以重载吗?
问题分析:为什么是静态方法?
静态修饰符:该修饰符的意思是静态的。简单理解就是static修饰符修饰的成员属于类本身,而不是属于类的实例。静态成员不能直接访问非静态成员。
当JVM调用这个main方法时,它肯定不会先创建这个主类的对象,然后通过该对象来调用该方法。相反,它直接通过类调用此方法。因此,需要使用static修饰符来修饰这个类。
其实这里如果要扩展的话,也可以比较static和instance。
为什么该方法没有返回参数?
该方法被void修饰,表示该方法不需要返回值。由于main方法是由JVM调用的,所以将返回值返回给JVM是没有意义的,所以该方法没有返回值,所以使用了void。
为什么这个方法叫main?
该 main() 方法的声明为:public static void main(String args[])。必须这样定义,这是Java规范。
为什么这样定义呢?和JVM的运行有关系。
当一个类有main()方法时,执行命令“java类名”将启动虚拟机执行该类中的main方法。
用过Spring Boot、Dubbo的朋友应该知道,都是从main方法开始的。另外,还有我们使用的Tomcat。启动Tomcat时,也会调用main方法。
记住:main方法是Java程序的入口点。
为什么方法参数是数组?
main()方法中的字符串参数数组用于接收命令行输入参数。命令行参数之间用空格分隔。
如果我们使用dos命令运行程序,在类名后面添加一个或多个字符串(用空格分隔),JVM就会将这些值依次赋给args数组。
你熟悉System类吗?
System类的完整路径名是java.lang.System。翻译过来就是系统的意思。许多系统级的属性和控制方法都在这个类中。
构造函数
/** Don't let anyone instantiate this class */
private System() {
}
构造方法是private修饰的,并且主食还写着“Do not let Anyinstantiate this class”,也就是说这个类不能被实例化。
成员变量/方法
在System类中,无论是成员变量还是成员方法都是静态修饰的(static),这样我们就可以非常方便的使用它们。
成员变量的使用
控制台输出“Hello, Lao Tian!”
System.out.println("老田,您好!")
这是系统调用的成员变量。 out 变量定义如下:
public final static PrintStream out = null;
成员方法的使用
如上所述,System的成员方法也是静态的。
获取当前毫秒数
System.currentTimeMillis()
其中,currentTimeMillis方法的定义:
public static native long currentTimeMillis();
在开发过程中,很多人通常习惯使用new Date()来获取当前时间。 newDate() 所做的实际上是调用 System.currentTimeMillis()。如果只需要毫秒,可以使用System.currentTimeMillis()而不是new Date(),这样会更高效。
三个成员变量 in、out 和 err
System包含三个成员变量in、out和err,分别代表标准输入流(键盘输入)、标准输出流(显示)和标准错误输出流(显示)。
//标准输入流
public final static InputStream in;
//标准输出流
public final static PrintStream out;
//标准错误流
public final static PrintStream err;
可见System中的out和in并不是内部类,而是成员变量。 out是PrintStream的final static,用于修改变量。另外,out可以调用PrintStream中的方法。例如,System.out.println()中的println()是PrintStream中的输出方法。
常用方法
System中有很多方法,我们不需要全部学习。我们只需要获取常用的即可。太多了,所以只选择一些真正有用的。
数组复制()方法
该方法被定义为本机级别,数组复制。
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
参数解释:
currentTimeMillis() 方法
返回毫秒数。这个比较简单,就像Date类中的getTime方法一样。
public static native long currentTimeMillis();
补充
时间单位换算:
1 秒 = 1000 毫秒 (ms) 1 毫秒 = 1/1,000 秒 (s)
1 秒 = 1,000,000 微秒 (μs) 1 微秒 = 1/1,000,000 秒 (s)
1 秒 = 1,000,000,000 纳秒 (ns) 1 纳秒 = 1/1,000,000,000 秒 (s)
1 秒 = 1,000,000,000,000 皮秒 (ps) 1 皮秒 = 1/1,000,000,000,000 秒 (s)
1 分钟 = 60 秒
1 小时 = 60 分钟 = 3600 秒
getProperty() 方法
该方法是获取系统属性。
方法定义:
private static Properties props;
public static String getProperty(String key, String def) {
checkKey(key);
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertyAccess(key);
}
return props.getProperty(key, def);
}
//Properties是Hashtable的子类
public class Properties extends Hashtable<Object,Object> {
...
}
这里的Properties你可能不太熟悉,但它们是Hashtable的子类。很少见到Hashtable,今天终于看到了。
String userHome = System.getProperty("user.home");
System.out.println(userHome);
估计很多人都没用过这个方法,有时间的话也可以尝试一下。
GC()方法
告诉 JVM 建议执行垃圾收集。
方法定义:
public static void gc() {
Runtime.getRuntime().gc();
}
从定义中可以看出,gc()方法封装了Runtime.getRuntime().gc()。
注意
这个 gc() 方法只是建议 JVM 执行垃圾回收,JVM 可能会拒绝。
GC本身会定期自动运行,由JVM决定运行的时机。而且,当前版本有多种更智能的模式可供选择,并且会根据运行的机器自动进行选择,即使确实有性能改进。根据需求,GC运行机制也应该进行微调,而不是用这种方法来优化性能。
exit() 方法
退出虚拟机。
方法定义:
public static void exit(int status) {
Runtime.getRuntime().exit(status);
}
方法注释
终止当前正在运行的 Java 虚拟机。该参数用作状态代码;按照惯例,非零状态代码表示异常终止。此方法永远不会正常返回。
粗略地翻译一下: exit(int) 方法终止当前正在运行的 Java 虚拟机。参数为状态码。按照约定,非零状态码表示异常终止,0表示终止。此外,该方法永远不会正常返回。
一堂HelloWorld课提出这么多问题,你学会了吗?
1.
2.
3.
4.