1、请你说一下多态?
多态指同一个行为具有多个不同表现形式或形态的能力。它是面向对象程序设计(OOP)的一个重要特征。(封装、继承、多态—面向对象编程的三大特性)如果一个语言只支持类而不支持多态,只能说明它是基于对象的,而不是面向对象的。

多态就是同一个接口,使用不同的实例而执行不同操作,如图所示:
【面试题】语言基础-1
多态性是对象多种表现形式的体现:
现实中,比如我们按下 F1 键这个动作:
如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;
如果当前在 Word 下弹出的就是 Word 帮助;
在 Windows 下弹出的就是 Windows 帮助和支持。
同一个事件发生在不同的对象上会产生不同的结果。

多态的优点:

  1. 消除类型之间的耦合关系2. 可替换性3. 可扩充性4. 接口性5. 灵活性6. 简化

多态存在的三个必要条件:继承、重写、父类引用指向子类对象

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。

Java中多态性的表现: 多态性,可以理解为一个事物的多种形态。同样python中也支持多态,但是是有限的的支持多态性,主要是因为python中变量的使用不用声明,所以不存在父类引用指向子类对象的多态体现,同时python不支持重载。在python中 多态的使用不如Java中那么明显,所以python中刻意谈到多态的意义不是特别大。

Python中多态的作用:让具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容(功能)的函数。

Python中多态的特点
1、只关心对象的实例方法是否同名,不关心对象所属的类型;
2、对象所属的类之间,继承关系可有可无;
3、多态的好处可以增加代码的外部调用灵活度,让代码更加通用,兼容性比较强;
4、多态是调用方法的技巧,不会影响到类的内部设计。

2、请问Java中接口与抽象类是否相同?
【面试题】语言基础-1

抽象类和接口的相同点:
1.都不能被实例化
2.接口的实现类或抽象类的子类都只有实现了接口或抽象类中的方法后才能被实例化

不同点:
1.接口只有定义,其方法不能再接口中实现,只有实现接口的类才能实现接口中定义的方法,而抽象类的方法可以再抽象类中被实现。
2.接口需要用implements实现,抽象类只能被继承(extends)。
3.设计理念不同,接口是"has - a ",抽象类是"is -a "
4.接口中定义的成员变量默认修饰符为public static final(静态不能被修改),而且必须 给其赋初值。抽象类可以有自己的数据成员变量,也可以有非抽象的成员变量,而且抽象类中的成员变量默认为default(本包可见)。抽象类中的方法前面有abstract修饰,不能用private、static、synchronize、native修饰,同时方法必须以分号结尾,不带花括号。

3、垃圾回收机制
说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联系起来。在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给了JVM来处理。顾名思义,垃圾回收就是释放垃圾占用的空间。

3.1为什么需要垃圾回收
如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收。除非内存无限大,我们可以任性的分配而不回收,但是事实并非如此。所以,垃圾回收是必须的。

3.2哪些内存需要回收
所谓“要回收的垃圾”无非就是那些不可能再被任何途径使用的对象。找到这些对象的方法:引用计数法(这个算法的实现是,给对象中添加一个引用计数器,每当一个地方引用这个对象时,计数器值+1;当引用失效时,计数器值-1。任何时刻计数值为0的对象就是不可能再被使用的。这种算法使用场景很多,但是,Java中却没有使用这种算法,因为这种算法很难解决对象之间相互引用的情况。用于python);
可达性分析法(这个算法的基本思想是通过一系列称为“GC Roots”的对象作为起始点,从这些节点向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链(即GC Roots到对象不可达)时,则证明此对象是不可用的)
那么问题又来了,如何选取GCRoots对象呢?在Java语言中,可以作为GCRoots的对象包括下面几种:
(1). 虚拟机栈(栈帧中的局部变量区,也叫做局部变量表)中引用的对象。
(2). 方法区中的类静态属性引用的对象。
(3). 方法区中常量引用的对象。
(4). 本地方法栈中JNI(Native方法)引用的对象。

3.3四种引用状态
将引用分为强引用、软引用、弱引用、虚引用4种,这4种引用强度依次减弱。
1、强引用
代码中普遍存在的类似"Object obj = new Object()"这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。
2、软引用
描述有些还有用但并非必需的对象。在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围进行二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。Java中的类SoftReference表示软引用。
3、弱引用
描述非必需对象。被弱引用关联的对象只能生存到下一次垃圾回收之前,垃圾收集器工作之后,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。Java中的类WeakReference表示弱引用。
4、虚引用
这个引用存在的唯一目的就是在这个对象被收集器回收时收到一个系统通知,被虚引用关联的对象,和其生存时间完全没关系。Java中的类PhantomReference表示虚引用。

【面试题】语言基础-1对于可达性分析算法而言,未到达的对象并非是“非死不可”的,若要宣判一个对象死亡,至少需要经历两次标记阶段。

3.4方法区的垃圾回收
方法区的垃圾回收主要回收两部分内容:1. 废弃常量。2. 无用的类。既然进行垃圾回收,就需要判断哪些是废弃常量,哪些是无用的类。
如何判断无用的类呢?需要满足以下三个条件

  1. 该类的所有实例都已经被回收,即Java堆中不存在该类的任何实例。
  2. 加载该类的ClassLoader已经被回收。
  3. 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
    满足以上三个条件的类可以进行垃圾回收,但是并不是无用就被回收。

3.5垃圾收集算法
1、标记-清除(Mark-Sweep)算法
分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,标记完成后统一回收所有被标记的对象。
这种算法的不足主要体现在效率和空间,从效率的角度讲,标记和清除两个过程的效率都不高;从空间的角度讲,标记清除后会产生大量不连续的内存碎片, 内存碎片太多可能会导致以后程序运行过程中在需要分配较大对象时,无法找到足够的连续内存而不得不提前触发一次垃圾收集动作。
【面试题】语言基础-12、复制(Copying)算法
复制算法是为了解决效率问题而出现的,它将可用的内存分为两块,每次只用其中一块,当这一块内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已经使用过的内存空间一次性清理掉。这样每次只需要对整个半区进行内存回收,内存分配时也不需要考虑内存碎片等复杂情况,只需要移动指针,按照顺序分配即可。
【面试题】语言基础-1 不过这种算法有个缺点,内存缩小为了原来的一半,这样代价太高了。现在的商用虚拟机都采用这种算法来回收新生代,不过研究表明1:1的比例非常不科学,(因此新生代的内存被划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor。每次回收时,将Eden和Survivor中还存活着的对象一次性复制到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor空间。HotSpot虚拟机默认Eden区和Survivor区的比例为8:1,意思是每次新生代中可用内存空间为整个新生代容量的90%。当然,我们没有办法保证每次回收都只有不多于10%的对象存活,当Survivor空间不够用时,需要依赖老年代进行分配担保(Handle Promotion))

3、标记-整理(Mark-Compact)算法
复制算法在对象存活率较高的场景下要进行大量的复制操作,效率很低。万一对象100%存活,那么需要有额外的空间进行分配担保。老年代都是不易被回收的对象,对象存活率高,因此一般不能直接选用复制算法。根据老年代的特点,有人提出了另外一种标记-整理算法,过程与标记-清除算法一样,不过不是直接对可回收对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉边界以外的内存。
【面试题】语言基础-14、分代收集算法
现代商用虚拟机基本都采用分代收集算法来进行垃圾回收。这种算法没什么特别的,无非是上面内容的结合罢了,根据对象的生命周期的不同将内存划分为几块,然后根据各块的特点采用最适当的收集算法。
大批对象死去、少量对象存活的(新生代),使用复制算法,复制成本低;对象存活率高、没有额外空间进行分配担保的(老年代),采用标记-清理算法或者标记-整理算法。

3.6垃圾收集器
Java的堆内存基于Generation算法(Generational Collector)划分为新生代、年老代和持久代。新生代又被进一步划分为Eden和Survivor区,最后Survivor由FromSpace(Survivor0)和ToSpace(Survivor1)组成。所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx和-Xms来控制。分代收集基于这样一个事实:不同的对象的生命周期是不一样的。因此,可以将不同生命周期的对象分代,不同的代采取不同的回收算法进行垃圾回收(GC),以便提高回收效率。
按执行机制划分Java有四种类型的垃圾回收器:
(1)串行垃圾回收器(Serial Garbage Collector)
(2)并行垃圾回收器(Parallel Garbage Collector)
(3)并发标记扫描垃圾回收器(CMS Garbage Collector)
(4)G1垃圾回收器(G1 Garbage Collector)

相关文章:

  • 2021-06-07
  • 2022-01-17
  • 2021-11-29
  • 2021-12-06
  • 2022-01-15
  • 2022-03-10
  • 2022-12-23
猜你喜欢
  • 2021-05-30
  • 2021-05-18
  • 2021-05-20
  • 2021-11-24
  • 2021-10-06
相关资源
相似解决方案