Java六神面试宝典————基础篇

1.Java中的基本数据类型有哪些?

byte short int long float double boolean char

2.面向对象的特征有哪些?

抽象、继承、封装、多态。

        抽象是将一类对象的共同特征总结出来的过程。包括数据抽象行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。

        继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类;得到继承信息的类被称为子类。

        封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。将具体的实现细节对调用者隐藏掉。

        多态是指允许不同的子类型的对象对同一消息做出不同的响应。工厂方法模式中就是充分利用了多态的特性,结合一些具体的实现细节,比如继承、方法重载等,根据里式替换原则,在调用父类的地方使用子类对象,可以实现更多样的行为。

3.访问修饰符有哪些?区别是什么?


4.String是基本数据类型吗?对String类型的理解。

String不是基本类型,是引用类型,基本类型只有八个。Java中类型包括基本类型引用类型 枚举类型

String类是java.lang包下的重要组成。

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {

java程序中的所有字符串字面量(如“abc”)都作为此类的实例。

字符串是常亮:意味着它们的值在创建之后不能更改。字符串缓冲区StringBuffer支持可变的字符串。因为String对象是不可变的,所以可以共享。

由于String内部实际上是一个char数组,因此:

String str = "abc";
     等效于: 
char data[] = {'a', 'b', 'c'};
String str = new String(data);

String的equals方法

public boolean equals(Object anObject) 

参数是String类型且与此字符串表示相同字符序列,结果为true。即比较的是内容,而不是内存地址。

下面这句代码在内存中创建了几个对象?

String s1 = new String("abc");//创建了两个对象,分别保存在常量池和堆内存中
new进堆内存,常量池一个对象“abc”,堆内存一个对象“abc”的一个副本。这样是创建了 两个对象

内存中有一个常量池,当我们创建常量时,系统先看常量池中有没有这个常量,如果有,则不创建对象,直接引用这个常量。

另外,java语言中的“+”字符串拼接符号,是通过StringBuilder和append来实现的,而且是每一个“+”都会创建一个StringBuilder对象,因此效率非常低。但是这里注意,通过+拼接虽然是通过在创建StringBuilder来实现,但是最终生成的字符串并不是存储在堆内存中,而是仍然保存在常量池中,测试代码如下:

String s = "abc" + "d";
String s1 = "abcd";
System.out.println(s == s1); // true

5.float f = 3.4;是否正确?

答:不正确。3.4是双精度数,将双精度型(double)赋值给浮点型(float)属于向下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换float f = (float)3.4;或者写成float f = 3.4f;  。

6.int和Integer有什么区别?

答:Java语言虽然是面向对象的编程语言,但是为了操作方便,依然引入了int等并不是表示对象的八种基本数据类型。让int等基本数据类型可以像其他对象那样完成某些动作,Java将八大基本数据类型都配备了封装类,Integer就是int的封装类。并且添加了自动拆装箱特性,开发者可以轻松的实现int与Integer之间的转换。

下面一个面试题:

Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
System.out.println(f1 == f2);// true
System.out.println(f3 == f4);// false

解析:

当一个int类型赋值给Integer对象的时候会隐式地调用valueOf方法,而valueOf方法内部又使用了一个叫IntegerCache 的静态内部类。这个类完成了一系列静态功能,使得:如果整型字面量的值在 -128到127之间,那么不会new新的Integer对象,而是直接引用常量池中的Integer对象

7. &和&& 的区别?

答:&&是“短路与”逻辑运算符,左面的表达式如果是false那么程序不会继续判断右面的表达式的值,而&不管左面的值是否为false都会完成两遍的逻辑计算。在大多数场合下我们需要的是&&而不是&。

8.Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?

答:Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11。四舍五入的原理是在参数上加0.5然后进行下取整。

9.switch 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?
答:在Java 5以前,switch(expr)中,expr只能是byte、short、char、int。从Java 5开始,Java中引入了枚举类型,expr也可以是enum类型,从Java 7开始,expr还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。

10.用最有效率的方法计算2乘以8?

答: 2 << 3(左移3位相当于乘以2的3次方,右移3位相当于除以2的3次方)。

11.数组有没有length()方法?String有没有length()方法?
答:数组没有length()方法,有length 的属性。String 有length()方法。JavaScript中,获得字符串的长度是通过length属性得到的。

12.构造器(constructor)是否可被重写(override)?
答:构造器不能被继承,因此不能被重写,但可以被重载。

13.请说明一下equals()方法和hash code的关系,实现equals()方法的重写。

答:如果两个对象x和y满足x.equals(y),那么他们的哈希码应当相同。

Java对于 equals方法和hashCode方法是这样规定的:

(1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;
(2)如果两个对象的hashCode相同,它们并不一定相同。

equals()方法的特性:

自反性(x.equals(x)必须返回true);
对称性(x.equals(y)返回true时,y.equals(x)也必须返回true);
传递性(x.equals(y)和y.equals(z)都返回true时,x.equals(z)也必须返回true);
一致性(当x和y引用的对象信息没有被修改时,多次调用x.equals(y)应该得到同样的返回值);
对于任何非null值的引用x,x.equals(null)必须返回false。

equals()方法和hashCode()方法重写:

//经典方式(17和31散列码思想)
public class User {
    private String name;
    private int age;
    private String passport;
    //getters and setters, constructor
    @Override
    public boolean equals(Object o) {
        if (o == this) return true;
        if (!(o instanceof User)) {
            return false;
        }
        User user = (User) o;
        return user.name.equals(name) &&
                user.age == age &&
                user.passport.equals(passport);
    }
    //Idea from effective Java : Item 9
    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + name.hashCode();
        result = 31 * result + age;
        result = 31 * result + passport.hashCode();
        return result;
    }
}
//JDK7+
import java.util.Objects;

public class User {
    private String name;
    private int age;
    private String passport;

    //getters and setters, constructor

    @Override
    public boolean equals(Object o) {
        if (o == this) return true;
        if (!(o instanceof User)) {
            return false;
        }
        User user = (User) o;
        return age == user.age &&
                Objects.equals(name, user.name) &&
                Objects.equals(passport, user.passport);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, passport);
    }
}
14.是否可以继承String类?
答:String 类是final类,不可以被继承。继承String本身就是一个错误的行为,对String类型最好的重用方式是关联关系(Has-A)和依赖关系(Use-A)而不是继承关系(Is-A)。

15.当一个对象被当做参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

答:是值传递。Java语言的方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值实际上是对象的额内存地址。对象中的属性可以在被调用过程中被改变。但是如果是将String或int等变量直接作为参数传入方法,修改其值时无法对调用方起到影响的。正是如此,在Java编写的代码中才会出现大量的Wrapper类(将需要通过方法调用修改的变量置于一个Wrapper类中,再将Wrapper对象传入方法)。

public class Demo {

    public static void main(String[] args) {
        int i = 0;
        change(i);// 将变量直接传入
        System.out.println(i);// 0 调用方
    }
    
    public static void change(int i){
        i = 10;
    }
}
public class Demo {

    public static void main(String[] args) {
        A a = new A();
        System.out.println(a.age);// 0 
        change(a);
        System.out.println(a.age);// 10 Wrapper类A将age进行封装
    }
    
    public static void change(A a){
        a.age = 10;
    }
}

class A {
    public int age;
}
按值传递指的是,在方法调用时,传递的参数是按值的拷贝传递。但是Wrapper类则是将引用的对象地址值传递给参数的。注意这点区别。

16.抽象类与接口异同?

同:
1.抽象类和接口可以定义引用,但是不能直接实例化。
2.一个类继承了抽象类或接口,除非是其本身也是抽象类,否则,必须实现全部抽象方法。
异:
1.抽象类中可以定义构造器,可以有抽象方法和具体方法,而接口中不能定义构造器,方法也必须全是抽象方法。
2.抽象类的成员可以由四种访问权限修饰,但是接口中的成员全是public
3.抽象类中可以定义成员变量,接口中定义的成员变量实际上都是常量。
4.有抽象方法,一定是抽象类,但反过来抽象类,不一定有抽象方法。
5.继承关系:接口可以继承接口,抽象类可以实现接口,接口不能继承抽象类

17.静态嵌套类(Static Nested Class)与内部类(Inner Class)的区别?

18.抽象方法能否被static修饰?能否被Native修饰?能否被synchronized修饰?

答:都不能。抽象方法需要子类重写,static修饰的类静态类无法被重写。Native是用来修饰本地方法的修饰符,不属于Java代码。synchronized和方法的实现细节有关,抽象方法没有方法体,即没有实现细节,因此无法被synchronized修饰。

19.静态方法能否调用非静态方法?

答:不可以,静态方法只能访问静态成员,因为非静态方法的调用首先要创建对象,在调用静态方法时,可能对象并没有被正确的初始化。

20.











猜你喜欢

转载自blog.csdn.net/u014745069/article/details/79822999