java基础-常见面试题(二)

  1. 动态代理基于什么原理?谈谈java反射机制。
    • 代理模式是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个真实对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
    • 反射机制是java 语言提供的一种基础功能,赋予程序在运行时自省的能力。通过反射我们可以直接操作类或对象,比如获取某个对象的类定义,获取类声明的属性和方法,

      调用方法或者构造对象,甚至可以运行时修改类定义。

    •  动态代理是一种方便运行时动态构建代理、动态处理代理方法调用的机制,很多场景都是利用类似的机制做到的,比如用来包装RPC调用、面向切面编程(AOP)。

      反射,是引用运行时的自省能力,赋予了java语言意外的活力,通多运行时操作元数据或对象,java可以灵活的操作运行时才能确定的信息,而动态代理则是一种在开发中应用广泛的技术,很多繁琐的重复编程都可以被动态代理优雅的解决。

  2. 比较 Vecter、ArrayList、LinkebList 的区别?
    • 三者都实现了集合框架中的List,也就是所谓的有序集合,因此功能比较相近,比如都提供按位置进行定位、添加、删除的操作,都提供便利器以遍历其内容等。

    •  Vector 是java 早期提供的线程安全的动态数组,如不需要考虑线程安全不推荐使用,毕竟同步是有额外的开销的。Vector 内部使用对象数组保存数据,可以根据需要自动的增加容量,当数组已满时,会创建新的数组,并拷贝原有的数组数据。

    •  ArrayList 是应用广泛的动态数组实现,本身不是线程安全的 ,性能好很多,与Vector 相似,Arraylist也可根据需要扩展容量,两者调整逻辑的区别是:Vector 扩容提高一倍,Arraylist 则提高50%。

    •  LinkedList 是java的双向链表 ,所以不需要像上面的那样扩容,他也不是线程安全的。

    •  不同容器适合的场景:

      •  Vector和ArrayList 作为动态数组,其内部元素以数组形式顺序存储的,所以非常适合随机访问的场合。除了尾部插入和删除元素,往往性能会相对较差,比如我们在中间位置插入一个元素,需移动后续所有元素。

      •  而linkedList 进行节点插入、删除高效很多,但是随机访问性能要比动态数组慢。

  3. 比较 Hashtable、HashMap、TreeMap 的不同?谈谈你对HashMap的掌握。
    • 都实现了Map接口,存储的内容是基于key-value的键值对映射,一个映射不能有重复的键,一个键最多只能映射一个值。

    •  Hashtable 早期的java类库提供的哈希表的实现,本身是同步的,不支持null 键和值,由于同步的开销,很少推荐使用。初始化的时候时,HashTable在不指定容量的情况下的默认容量是11,且不要求底层数组的容量一定要为2的整数次幂。HashMap默认的容量为16,且要求容量一定为2的整数次幂。

    •  HashMap 应用广泛的哈希表的实现,行为上大致与Hashtable 一致,主要区别在于HashMap 不同步,支持null 键和值,通常情况下,Hashmap 进行 put(),get()方法,可以达到常数时间的性能,他是绝大部分利用键值对存取场景的首选。

    •  TreeMap 则是基于红黑树的一种提供顺序访问的Map,和Hashmap 不同,他的get、put、remove操作都是O(log(n))的时间复杂度,具体顺序有Comparator 决定。

    •  HashMap的总结:HashMap基于哈希思想,实现对数据的读写。当键值对被传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,然后找到bucket位置来存储对象。当获取对象的时候,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap通过链表来解决碰撞问题,当碰撞发生时,对象将会储存在链表的下个节点中.HashMap在每个链表节点中储存键值对对象。当两个不同的键对象的hashcode相同时,它们会储存在同一个bucket位置的链表中,这时候就需要通过equals()方法来找到键值对。

  4. 接口与抽象类的区别?
    • 语法层面上的区别
      • 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;

      • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;

      • 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;

      • 一个类只能继承一个抽象类,而一个类却可以实现多个接口。

    • 设计层面上的区别
      • 抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。举个简单的例子,飞机和鸟是不同类的事物,但是它们都有一个共性,就是都会飞。那么在设计的时候,可以将飞机设计为一个类Airplane,将鸟设计为一个类Bird,但是不能将 飞行 这个特性也设计为类,因此它只是一个行为特性,并不是对一类事物的抽象描述。此时可以将 飞行 设计为一个接口Fly,包含方法fly( ),然后Airplane和Bird分别根据自己的需要实现Fly这个接口。然后至于有不同种类的飞机,比如战斗机、民用飞机等直接继承Airplane即可,对于鸟也是类似的,不同种类的鸟直接继承Bird类即可。从这里可以看出,继承是一个 "是不是"的关系,而 接口 实现则是 "有没有"的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比如鸟是否能飞(或者是否具备飞行这个特点),能飞行则可以实现这个接口,不能飞行就不实现这个接口。

      •  设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。什么是模板式设计?最简单例子,大家都用过ppt里面的模板,如果用模板A设计了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A了,如果它们的公共部分需要改动,则只需要改动模板A就可以了,不需要重新对ppt B和ppt C进行改动。而辐射式设计,比如某个电梯都装了某种报警器,一旦要更新报警器,就必须全部更新。也就是说对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。

posted @ 2020-07-11 11:20  小呆俊  阅读(72)  评论(0编辑  收藏  举报
/*标题彩虹滚动字*/ #blogTitle h1 a{ background-image: -webkit-gradient( linear, left top, right top, color-stop(0, #f22), color-stop(0.15, #f2f), color-stop(0.3, #22f), color-stop(0.45, #2ff), color-stop(0.6, #2f2), color-stop(0.75, #2f2), color-stop(0.9, #ff2), color-stop(1, #f22) ); color: transparent;-webkit-text-fill-color: transparent; -webkit-background-clip: text; -webkit-background-size: 200% 100%; -webkit-animation: maskedAnimation 2s infinite linear; -webkit-background-clip: text;-moz-background-clip: text;-ms-background-clip: text /*文字颜色变化*/ @keyframes maskedAnimation { 0% { background-position: 0 0; } 100% { background-pos