写给自己的Java面试题(1)
by 伊布
什么时候才相等?
对于基础类型来说,值相等则相等。
int a =3;
int b = 3;
System.out.println("a==b is " + (a==b));
//a==b is true
对于对象来说,“==”比较的其实是对象的引用,如果要比较两个对象是否相等,应该用.equals()。
Integer a = 3;
Integer b = 3;
Integer c = b;
System.out.println("a==b is " + (a==b));
System.out.println("c==b is " + (c==b));
System.out.println("a equals b is " + (a.equals(b)));
//a==b is false
c==b is true
a equals b is true
如果,把对象的类型由Integer改为自定义的类型呢?例如:
class TOT {
private int i;
TOT (int i){
this.i = i;
}
}
public class Main{
public static void main(String[] args) {
TOT a = new TOT(3);
TOT b = new TOT(3);
System.out.println("a equals b is " + a.equals(b));
}
}
//a equals b is false
为什么呢?还记得前面说的吗,对象之间.equals是调用了类的equals方法,class TOT继承自是Object,并且未覆盖equals方法,所以比较的时候还是使用的Object类的equals方法,而该方法使用对象的”引用”,显然不相等。
public class Object {
public boolean equals(Object obj) {
return (this == obj);
}
那应该怎么做才能让二者.equals相等呢?很简单,覆盖equals方法。
class TOT {
private int i;
TOT (int i){
this.i = i;
}
@Override
public boolean equals(Object obj) {
TOT tot = (TOT)obj;
return this.i == tot.i;
}
}
public class Main{
public static void main(String[] args) {
TOT a = new TOT(3);
TOT b = new TOT(3);
System.out.println("a equals b is " + a.equals(b));
}
}
//a equals b is true
static的用法?
准则:所有的static操作都发生在类加载时。 1、用于修饰类域(静态变量)
class x {
static int var1;
int var3;
}
静态成员的存储是独立于类的对象的,换句话说就是,该类所有对象的静态成员引用的是同一块内存(共享)。因此,无论是直接使用类名+变量名(如x.var1 = 1)来修改值,还是使用对象名+变量名(new x().var = 1),更新的都是同一块内存,会互相影响。
2、用于修饰类的方法(静态方法) static method实际是一些没有传入this引用的特殊方法,用户可以不经过new 对象就调用该方法。静态方法不能调用类的非静态方法,也无法访问非静态变量(没有this 指针)。
3、静态代码块 类定义时,可以将静态变量的处理放到类的静态代码块中,该代码块会在类初始化之前调用,所以如果给main类的静态代码块,会在main入口之前先执行,因为main入口执行之前,需要先加载main类。
public class Main {
static {
System.out.println("Static Code");
}
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
//Static Code
//Hello World!
需要注意一种特殊情况:static修饰的集合引用。
static ArrayList<String> a = new ArrayList<String>();
这时,a作为引用,可以其引用的容器添加对象,并且各个对象、类是同一个容器,需要注意多线程的冲突问题。
this是什么
this是对本对象的引用。几种用法:
1、访问本对象的域,防止与方法的局部变量重名。
2、初始化对象。构造方法只能在构造方法中调用,且必须开始就调用,且只能调用一次。
public class X {
String str;
public X() {
this("a test");
}
public X(String str) {
this.str = str;
}
}
3、将本对象传递给其他方法。
public class X {
public void test () {
System.out.println(this);
}
@Overwrite
public String toString() {
return "X"
}
}
类的字段是否会自动初始化?局部变量呢?如果局部变量没有初始化,是编译报错,还是运行随机值呢?
会,不会,编译。跟C不一样,Java会尽量保证程序的安全。
main方法为什么要加static修饰字?
否则谁去new它呢。main方法调用本类内部的方法,该方法也需要为static
如何理解CLASSPATH?
指导解释器在哪些目录下查找.class文件。例如代码中import cn.datastart.debug.Debug
,那么解释器会在CLASSPATH指定的所有路径下查找./cn/datastart/debug/Debug.class
,找不到则会报错。
注意,jar包略有不同,如果要加到CLASSPATH的话需要带上jar包的名字(很好理解,jar包是多个.class打包而成,可以理解为一个压缩以后的目录)
java的权限设置有哪几种?他们的权限大小关系是?
public、包访问权限、protect、private。默认处于同一目录下的文件之间自动携带包访问权限。其范围关系:
public > protect > 包访问权限 > private
java的权限设置是针对谁的?是否可以设置类的权限?
针对类和类的成员,即域和方法。
可以设置类的权限,但类只有public和包访问权限。一个java文件最多有一个public类,该类全局可见。若不加public则表 包访问权限,即包内可见。
类不存在protect和private权限,但是可以通过设置类的构造器的权限,来间接设置类的private/protect权限。例如:
package cn.datastart.debug;
public class Debug {
private Debug() {}
如果构造器不加任何修饰符,则表示为包访问权限,那么在包cn.datastart.debug之外的代码中就无法new cn.datastart.debug.Debug;如果加上private,则表示谁都无法new该类的对象,那怎么用呢?可以给该类加一个public方法,在该方法中调用构造器,即,单例。
package cn.datastart.debug;
public class Debug {
public private Debug() { }
public static Debug getDebugInstance() {
return new Debug();
}
注意该方法一定是static,否则没有实例怎么调用呢。
64位机器上的int变量,是几个字节?
4个字节。java的int长度是固定的,与cpu是32位还是64位无关。
protected关键字用来做什么?
有些方法需要跨包使用,但又不想像public一样谁都可以用,可以用protected关键字允许继承该类的子类内访问。
Subscribe via RSS