面试总结一——基础知识

1.  ==和equals方法究竟有什么区别?

        a:==是比较运算符,而equals是方法,二者目的都是为了比较对象是否一致

        b:equals属于Object类的方法,不重写时与==等同,比较基本数据类型的值,比较引用对象的哈希值

        c:一般final修饰的类都重写了equals方法,比如String,Double,Integer等

        d:自定义类,为了比较内容是否一致,会重写hashCode和equals方法;

2.  静态变量和实例变量的区别?

        静态变量也叫作类变量,见名知意,是被static修饰的变量,属于类,在内存中独占一份,通过类名.变量名获取,

而实例变量,属于对象,通过引用名.变量名获取(但多数时候实例变量为private修饰,需要通过get方法获取)

3. Overload和Override的区别?

        'load'与‘ride’,也就是加载和重写。那么将方法比作加工厂,参数就是加工材料,每次加入的材料不同,生产同类或不同类的产品,重载就是这样的原理,同名方法,不同参数,返回类型相同或不同的结果。而重载就是在不同的地方用同样的加工厂,同样的材料,走不同流程,来获取同一类产品

4.  abstract class和interface有什么区别?

        应当从三个方面来说,分别是语法,定义,用途

        语法:

            a:抽象类,一言以蔽之,包罗万象,而接口,只能定义常量,抽象方法,静态方法,默认方法

            b:类只能继承一个抽象类,而接口能被多个类实现

        定义:

            抽象类是具体事物的共性抽象提取,而接口是某一行为的规范

        用途:

            抽象类用以代码重构,减少代码量,而接口用以规范开发,解耦合

5.   String,StringBuffer与StringBuilder的区别?

        为了确保String类的安全性,设计师将其设定为不可变类,避免被重写时引发未知混乱,并能将值相同的字符串,指向同一内存,节约资源。但如果要实现字符串拼接,采用String会短时间内反复创建大量对象,占用内存,故有了StringBuffer与StringBuilder的存在,二者都实现了可变字符串;但在多线程下,怎么保证可变字符串读写安全?于是有了StringBuffer,其大量方法被synchronized修饰。

6.  运行时异常与一般异常有何异同?

        异常主要分为两大类Error和Exception,而Exception又分为Runtime Exception 和Not Runtime Exception;

            Error:系统异常和编译异常,未系统不可捕捉错误

            Runtime Exception:运行期异常,是虚拟机的解释器对用户行为无法解释时报错

            Not Runtime Exception:在编译期即能检测出的错误

7. 深拷贝和浅拷贝的区别是什么?

        定义:

            浅克隆:根据原有对象内容,复制创建新的对象,新对象与被复制对象的属性,其引用指向于同一对象(属性不复制

            深克隆:作用于浅克隆类似,但是新对象属性,其引用指向于被复制对象的属性引用指向对象的复制(属性复制

        实现:        

              深克隆:被克隆类以及被克隆类的引用必须实现Serializable接口;其本质是对象流的序列化与反序列

              浅克隆:被克隆对象需要实现Cloneable接口,然后调用Object类的clone方法
        范例:
public class Test implements Cloneable, Serializable {
    int[]  t = {1,2,3};

    public Test shallowClone(Test t) throws CloneNotSupportedException {
        return (Test) t.clone();
    }

    public Test deepClone(Test t) throws CloneNotSupportedException, IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = null;
        ObjectInputStream ois = null;
        try {
            //将bos作为收集字节数组中介
            oos = new ObjectOutputStream(bos);
            //将传入参数student类写入bos中
            oos.writeObject(t);
            //将读取到数据传入ObjectInputStream
            ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
            return (Test) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            //JDK 1.7后引入 可以同时用| 优化代码可读性
            e.printStackTrace();
            return null;
        } finally {
            try {
                bos.close();
                oos.close();
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws CloneNotSupportedException, IOException {
        Test t1 = new Test();
       Test t2 = t1.deepClone(t1);
        Test t3 = t1.shallowClone(t1);
       System.out.println(t2.t.equals(t1.t));//false
        System.out.println(t3.t. equals(t1.t));//true
    }
}

8. switch语句能否作用在byte上,能否作用在long上,能否作用在String

        switch case支持六种数据类型

                整数型:byte,short,int

                字符型:char

                字符串:String(1.7以后)

                枚举:  Enum(1.7以后)

9. short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?

        这其中涉及了两点:类型转化和特殊运算,s1是short类型,与作为int类型的1相加后其结果值为int类型,而对于+=这类的运算,java解释器做了特殊优化,会自动判别结果类型。故而,s1 = s1 + 1存在类型不对的问题,而s1 +=1,是正确的

10. Math.round(11.5)等於多少? Math.round(-11.5)等於多少?

        Math类中提供了三个与取整有关的方法:ceilfloorround

            ceil: 其英文意义是天花板,该方法就表示向上取整,即获取大于或等于参数的最小整数

            floor: 其英文意义是地板,该方法就表示向下取整,即获取小于或等于参数的最小整数

        round:它表示“四舍五入”,算法为Math.round(x+0.5),即将原来的数字加上0.5后再向下取整,所以,Math.round(11.5)的结果为12Math.round(-11.5)的结果为-11

11. Java程序初始化的顺序是怎样的

        在JAVA语言中,当实例化对象时,对象所在类的所有成员变量首先要进行初始化,只有当所有类成员完成初始化后,才会调用对象所在类的构造函数创建对象。

        初始化一般遵循3个原则(优先级依次递减):

            1静态对象(变量)优先于非静态对象(变量)初始化,其中静态对象(变量)只初始化一次。而非静态对象(变量)可能会初始化多次

            2父类优先子类进行初始化

            3按照成员变量定义顺序进行初始化,即变量定义散布于定义方法之中,它们依然在任何方法(包括构造方法)被调用之前先初始化。

            Java程序初始化工作可以在许多不同的代码块中来完成,它们执行的顺序如下:(父类静态变量,父类静态代码块),(子类静态变量,子类静态代码块),(父类非静态变量,父类非静态代码块),父类构造函数,(子类非静态变量,子类非静态代码块),子类构造函数。

12. 简述面向对象的几大特征

    1封装:

        封装是保证软件部件具有优良的模块性的基础,封装的目标就是要实现软件部件的“高内聚、低耦合”,防止程序相互依赖性而带来的变动影响。在面向对象的编程语言中,对象是封装的最基本单位,面向对象的封装比传统语言的封装更为清晰、更为有力。面向对象的封装就是把描述一个对象的属性和行为的代码封装在一个“模块”中,也就是一个类中,属性用变量定义,行为用方法进行定义,方法可以直接访问同一个对象中的属性。通常情况下,只要记住让变量和访问这个变量的方法放在一起,将一个类中的成员变量全部定义成私有的,只有这个类自己的方法才可以访问到这些成员变量,这就基本上实现对象的封装。把握一个原则:把对同一事物进行操作的方法和相关的方法放在同一个类中,把方法和它操作的数据放在同一个类中。

    2.抽象:

        抽象就是找出一些事物的相似和共性之处,然后将这些事物归为一个类,这个类只考虑这些事物的相似和共性之处,并且会忽略与当前主题和目标无关的那些方面,将注意力集中在与当前目标有关的方面。例如,看到一只蚂蚁和大象,你能够想象出它们的相同之处,那就是抽象。抽象包括行为抽象和状态抽象两个方面。例如,定义一个Person类,如下:

    class Person{

              String name;

              int age;

    }

        人本来是很复杂的事物,有很多方面,但因为当前系统只需要了解人的姓名和年龄,所以上面定义的类中只包含姓名和年龄这两个属性,这就是一种抽像,使用抽象可以避免考虑一些与目标无关的细节。

    3.继承:

        在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并可以加入若干新的内容,或修改原来的方法使之更适合特殊的需要,这就是继承。继承是子类自动共享父类数据和方法的机制,这是类之间的一种关系,提高了软件的可重用性和可扩展性

    4多态:

        多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。多态性增强了软件的灵活性和扩展性。例如,下面代码中的UserDao是一个接口,它定义引用变量userDao指向的实例对象由daofactory.getDao()在执行的时候返回,有时候指向的是UserJdbcDao这个实现,有时候指向的是UserHibernateDao这个实现,这样,不用修改源代码,就可以改变userDao指向的具体类实现,从而导致userDao.insertUser()方法调用的具体代码也随之改变,即有时候调用的是UserJdbcDaoinsertUser方法,有时候调用的是UserHibernateDaoinsertUser方法:

        UserDao userDao =daofactory.getDao(); userDao.insertUser(user);

13. 两种参数传递方式

    1.值传递:实参将值传递给形参,形参只是用实参的值初始化一个临时的存储单元,因此虽然值相同,但是存储单元不同,因此对形参的改变不会影响实参的值。

    2.引用传递:传递的是对象(对象的地址),形参与实参同一块存储单元,对形参的改变

会影响实参的值

       原始数据类型按值传递,包装类型按引用传递。

实例

package com.homework.labmanager.labmanager.utils;

/**
 * @author sunyiran
 * @date 2018-07-11
 * @purpose
 */
public class Test {

    int a = 1;
    Integer b =1;

    public  void valPor(int a) {
        a = 2;
    }

    public void citePor(Integer b) {
        b = 2;
    }

    public static void main(String[] args) {
        Test t = new Test();
        //测试基本数据类
        t.valPor(t.a);
        System.out.println("a = " + t.a);//结果为1
        //测试包装类
        t.citePor(t.b);
        System.out.println("b = " + t.b);//结果为1
    }
}
    结论:可以借用局部变量理解,有成员变量a,b和局部变量a,b;局部变量a = 成员变量a,局部变量b = 成员变量 b,在方法结束后局部变量销毁,并不改变成员变量a与b的实际值











  


        

        

    










猜你喜欢

转载自blog.csdn.net/qq_35813653/article/details/80954787