CVTE 电话面试

Stay Hungry, Stay Foolish.

面向对象三大特性

  1. 封装
  2. 继承
  3. 多态

多态有什么好处

什么是多态?

同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性。简单的说:就是用基类的引用指向子类的对象。

为什么要用多态?

封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态除了代码的复用性外,还可以解决项目中紧偶合的问题,提高程序的可扩展性。耦合度讲的是模块与模块之间,代码与代码之间的关联度,通过对系统的分析把他分解成一个一个子模块,子模块提供稳定的接口,达到降低系统耦合度的目的,模块与模块之间尽量使用模块接口访问,而不是随意引用其他模块的成员变量。

多态的好处

  1. 应用程序不必为每一个派生类编写功能调用,只需要对抽象基类进行处理即可。大大提高程序的可复用性。// 继承
  2. 派生类的功能可以被基类的方法或引用变量所调用,这叫向后兼容,可以提高可扩充性和可维护性。 // 多态的真正作用

实现多态的方式

  1. 实现接口
  2. 继承父类,重写父类方法;或继承的是抽象类,实现抽象方法
  3. 同一个类中,方法重载

创建对象实例的方式有哪些?

  1. 使用new关键字

    User user = new User();
  2. 使用反射机制

    // 方法1
    User user = (User) Class.forName("package.User").newInstance();
    // 方法2
    User user = User.class.newInstance();
    // 调用构造方法
    Constructor<User> constructor = User.class.getConstructor();
    User user = constructor.newInstance();
  3. 使用clone方法

    public class CloneTest {
    // clone 被 protected 修饰
    public static void main(String[] args) {
    CloneTest cloneTest = new CloneTest();
    try {
    CloneTest copy = (CloneTest) cloneTest.clone();
    } catch (CloneNotSupportedException e) {
    e.printStackTrace();
    }
    }
    }
  4. 使用反序列化

    import java.io.*;

    public class SerializableDemo {
    public static void main(String[] args) {
    // Initializes The Object
    User user = new User("Leo");
    System.out.println(user);

    // Write Obj to File(序列化)
    try (ObjectOutputStream oos = new ObjectOutputStream(
    new FileOutputStream("tempFile"))) {
    oos.writeObject(user);
    } catch (IOException e) {
    e.printStackTrace();
    }

    // Read Obj from File(反序列化)
    File file = new File("tempFile");
    try (ObjectInputStream ois = new ObjectInputStream(
    new FileInputStream(file))) {
    User newUser = (User) ois.readObject();
    System.out.println(newUser);

    if (!file.delete()) {
    throw new RuntimeException("无法删除该文件:" + file);
    }
    } catch (IOException | ClassNotFoundException e) {
    e.printStackTrace();
    }

    }
    }

    class User implements Serializable {
    private static final long serialVersionUID = 1565116950906132146L;
    private String name;
    User(String name) {
    this.name = name;
    }
    @Override
    public String toString() {
    return "User{" +
    "name='" + name + '\'' +
    '}';
    }
    }

double 和 BigDecimal 比较

BigDecimal的缺点:

  1. 占用更多内存;
  2. 与基本类型相比,不能使用数学运算符,计算方式更复杂;
  3. 执行效率慢。

BigDecimal的优点:

  1. 精度更高,避免出现double运算精度异常的问题;
  2. 更灵活和方便的小数点处理(支持多种舍入模式)。

IO 和 NIO 比较

IO NIO
面向流 面向缓冲区、基于通道
阻塞 IO 非阻塞 IO
选择器(Selectors)

Hashtable 和 HashMap 比较

  1. HashMap可以插入keyvaluenullEntry
  2. HashMapHashtablecontains方法移除了,改成containsValuecontainsKey。因为 contains 方法容易让人引起误解;
  3. HashTable 的迭代器是fail-fast迭代器;
  4. HashMap不能保证随着时间的推移 Map 中的元素次序是不变的。
  5. HashTable 的方法均使用 synchronized 修饰。

HashMap 的扩容策略

三个关键参数

参数 含义
capacity table 容量大小,默认为 16。且必须保证该值为 2 的 n 次方
size 键值对的数量
threshold size 的临界值,当 size 大于等于 threshold 就必须进行扩容操作
loadFactor 装载因子,table 能够使用的比例,threshold=capacity*loadFactor

当需要扩容时,capacity将变为原来的两倍。

介绍下红黑树

红黑树是一种自平衡二叉查找树。它可以在O(log n)时间内完成查找、插入和删除,这里 n 是树中元素的数目。

红黑树相对于AVL树来说,牺牲了部分平衡性以换取插入/删除操作时少量的旋转操作,整体来说性能要优于AVL树。

红黑树还不了解,待补充……

自定义注解

四种元注解

名称 作用
@Target 描述注解的作用目标
@Retention 需要在什么级别保存该注解信息,用于描述注解的生命周期
@Documented 表明注解包含在 Javadoc 生成的文档中
@Inherited 表明注解可以被继承

@Target的作用目标包括:

  • ElementType.TYPE:接口、类、枚举、注解
  • ElementType.FIELD:字段、枚举的常量
  • ElementType.METHOD:方法
  • ElementType.PARAMETER:方法参数
  • ElementType.CONSTRUCTOR:构造函数
  • ElementType.LOCAL_VARIABLE:局部变量
  • ElementType.ANNOTATION_TYPE:注解
  • ElementType.PACKAGE:包

@Retention注解的保留策略包括:

  • RetentionPolicy.SOURCE:仅存在于源码中,在字节码文件中不包含

  • RetentionPolicy.CLASS:默认。会在字节码文件中存在,但运行时无法获得

  • RetentionPolicy.RUNTIME:会在字节码文件中存在,运行时可通过反射获取到

自定义注解示例模板

@元注解
public @interface 注解名 {
修饰符 返回值 属性名() default + something;
}

自定义注解的解析:自己选取一个合适的时机和位置,比如工厂类创建对象实例的方法中,根据反射技术,拿到用户想要创建的对象上的注解,然后根据注解去做相应的初始化工作。再比如校验性注解,在一个校验方法中,传入对象实例,根据反射拿到注解注明的校验信息,然后判断该实例是否合法。

介绍几种常用的设计模式

单例:确保一个类只有一个实例,并提供该实例的全局访问点。

简单工厂:在创建一个对象时不向客户暴露内部细节,并提供一个创建对象的通用接口。

观察者:定义对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖都会收到通知并且自动更新状态。

代理:控制对其它对象的访问。

其他问题

  1. 自己项目的一些问题;
  2. 谈谈职业规划;
  3. 平常如何学习技术;
手滑了就鼓励一下吧~