Java编程思想重点整理笔记分析.docx

上传人:b****1 文档编号:2417819 上传时间:2022-10-29 格式:DOCX 页数:24 大小:29.91KB
下载 相关 举报
Java编程思想重点整理笔记分析.docx_第1页
第1页 / 共24页
Java编程思想重点整理笔记分析.docx_第2页
第2页 / 共24页
Java编程思想重点整理笔记分析.docx_第3页
第3页 / 共24页
Java编程思想重点整理笔记分析.docx_第4页
第4页 / 共24页
Java编程思想重点整理笔记分析.docx_第5页
第5页 / 共24页
点击查看更多>>
下载资源
资源描述

Java编程思想重点整理笔记分析.docx

《Java编程思想重点整理笔记分析.docx》由会员分享,可在线阅读,更多相关《Java编程思想重点整理笔记分析.docx(24页珍藏版)》请在冰豆网上搜索。

Java编程思想重点整理笔记分析.docx

Java编程思想重点整理笔记分析

目录

1.Java中的多态性理解(注意与C++区分)1

2.is-a关系和is-like-a关系4

3.运行时类型信息(RTTI+反射)4

4.代理模式与Java中的动态代理11

5.即时编译器技术—JIT14

6.访问控制权限15

7.组合和继承之间的选择16

8.final关键字16

9.策略设计模式与适配器模式的区别17

10.内部类17

11.String类型—不可变18

12.序列化控制22

 

1.Java中的多态性理解(注意与C++区分)

∙Java中除了static方法和final方法(private方法本质上属于final方法,因为不能被子类访问)之外,其它所有的方法都是动态绑定,这意味着通常情况下,我们不必判定是否应该进行动态绑定—它会自动发生。

ofinal方法会使编译器生成更有效的代码,这也是为什么说声明为final方法能在一定程度上提高性能(效果不明显)。

o如果某个方法是静态的,它的行为就不具有多态性:

oclassStaticSuper{

opublicstaticStringstaticGet(){

oreturn"BasestaticGet()";

o}

o

opublicStringdynamicGet(){

oreturn"BasedynamicGet()";

o}

o}

o

oclassStaticSubextendsStaticSuper{

opublicstaticStringstaticGet(){

oreturn"DerivedstaticGet()";

o}

o

opublicStringdynamicGet(){

oreturn"DeriveddynamicGet()";

o}

o}

o

opublicclassStaticPolymorphism{

o

opublicstaticvoidmain(String[]args){

oStaticSupersup=newStaticSub();

oSystem.out.println(sup.staticGet());

oSystem.out.println(sup.dynamicGet());

o}

o

o}

输出:

BasestaticGet()

DeriveddynamicGet()

∙构造函数并不具有多态性,它们实际上是static方法,只不过该static声明是隐式的。

因此,构造函数不能够被override。

∙在父类构造函数内部调用具有多态行为的函数将导致无法预测的结果,因为此时子类对象还没初始化,此时调用子类方法不会得到我们想要的结果。

∙classGlyph{

∙voiddraw(){

∙System.out.println("Glyph.draw()");

∙}

∙Glyph(){

∙System.out.println("Glyph()beforedraw()");

∙draw();

∙System.out.println("Glyph()afterdraw()");

∙}

∙}

∙classRoundGlyphextendsGlyph{

∙privateintradius=1;

∙RoundGlyph(intr){

∙radius=r;

∙System.out.println("RoundGlyph.RoundGlyph().radius="+radius);

∙}

∙voiddraw(){

∙System.out.println("RoundGlyph.draw().radius="+radius);

∙}

∙}

∙publicclassPolyConstructors{

∙publicstaticvoidmain(String[]args){

∙newRoundGlyph(5);

∙}

∙}

输出:

Glyph()beforedraw()

RoundGlyph.draw().radius=0

Glyph()afterdraw()

RoundGlyph.RoundGlyph().radius=5

为什么会这样输出?

这就要明确掌握Java中构造函数的调用顺序:

(1)在其他任何事物发生之前,将分配给对象的存储空间初始化成二进制0;

(2)调用基类构造函数。

从根开始递归下去,因为多态性此时调用子类覆盖后的draw()方法(要在调用RoundGlyph构造函数之前调用),由于步骤1的缘故,我们此时会发现radius的值为0;

(3)按声明顺序调用成员的初始化方法;

(4)最后调用子类的构造函数。

∙只有非private方法才可以被覆盖,但是还需要密切注意覆盖private方法的现象,这时虽然编译器不会报错,但是也不会按照我们所期望的来执行,即覆盖private方法对子类来说是一个新的方法而非重载方法。

因此,在子类中,新方法名最好不要与基类的private方法采取同一名字(虽然没关系,但容易误解,以为能够覆盖基类的private方法)。

∙Java类中属性域的访问操作都由编译器解析,因此不是多态的。

父类和子类的同名属性都会分配不同的存储空间,如下:

∙//Directfieldaccessisdeterminedatcompiletime.

∙classSuper{

∙publicintfield=0;

∙publicintgetField(){

∙returnfield;

∙}

∙}

∙classSubextendsSuper{

∙publicintfield=1;

∙publicintgetField(){

∙returnfield;

∙}

∙publicintgetSuperField(){

∙returnsuper.field;

∙}

∙}

∙publicclassFieldAccess{

∙publicstaticvoidmain(String[]args){

∙Supersup=newSub();

∙System.out.println("sup.filed="+sup.field+

∙",sup.getField()="+sup.getField());

∙Subsub=newSub();

∙System.out.println("sub.filed="+sub.field+

∙",sub.getField()="+sub.getField()+

∙",sub.getSuperField()="+sub.getSuperField());

∙}

∙}

输出:

sup.filed=0,sup.getField()=1

sub.filed=1,sub.getField()=1,sub.getSuperField()=0

Sub子类实际上包含了两个称为field的域,然而在引用Sub中的field时所产生的默认域并非Super版本的field域,因此为了得到Super.field,必须显式地指明super.field。

2.is-a关系和is-like-a关系

∙is-a关系属于纯继承,即只有在基类中已经建立的方法才可以在子类中被覆盖,如下图所示:

基类和子类有着完全相同的接口,这样向上转型时永远不需要知道正在处理的对象的确切类型,这通过多态来实现。

∙is-like-a关系:

子类扩展了基类接口。

它有着相同的基本接口,但是他还具有由额外方法实现的其他特性。

缺点就是子类中接口的扩展部分不能被基类访问,因此一旦向上转型,就不能调用那些新方法。

3.运行时类型信息(RTTI+反射)

∙概念

RTTI:

运行时类型信息使得你可以在程序运行时发现和使用类型信息。

∙使用方式

Java是如何让我们在运行时识别对象和类的信息的,主要有两种方式(还有辅助的第三种方式,见下描述):

o一种是“传统的”RTTI,它假定我们在编译时已经知道了所有的类型,比如Shapes=(Shape)s1;

o另一种是“反射”机制,它运行我们在运行时发现和使用类的信息,即使用Class.forName()。

o其实还有第三种形式,就是关键字instanceof,它返回一个bool值,它保持了类型的概念,它指的是“你是这个类吗?

或者你是这个类的派生类吗?

”。

而如果用==或equals比较实际的Class对象,就没有考虑继承—它或者是这个确切的类型,或者不是。

∙工作原理

要理解RTTI在Java中的工作原理,首先必须知道类型信息在运行时是如何表示的,这项工作是由称为Class对象的特殊对象完成的,它包含了与类有关的信息。

Java送Class对象来执行其RTTI,使用类加载器的子系统实现。

无论何时,只要你想在运行时使用类型信息,就必须首先获得对恰当的Class对象的引用,获取方式有三种:

(1)如果你没有持有该类型的对象,则Class.forName()就是实现此功能的便捷途,因为它不需要对象信息;

(2)如果你已经拥有了一个感兴趣的类型的对象,那就可以通过调用getClass()方法来获取Class引用了,它将返回表示该对象的实际类型的Class引用。

Class包含很有有用的方法,比如:

packagertti;

interfaceHasBatteries{}

interfaceWaterProof{}

interfaceShoots{}

classToy{

Toy(){}

Toy(inti){}

}

classFancyToyextendsToy

implementsHasBatteries,WaterProof,Shoots{

FancyToy(){

super

(1);

}

}

publicclassRTTITest{

staticvoidprintInfo(Classcc){

System.out.println("Classname:

"+cc.getName()+

",isinterface?

["+cc.isInterface()+"]");

System.out.println("Simplename:

"+cc.getSimpleName());

System.out.println("Canonicalname:

"+cc.getCanonicalName());

}

publicstaticvoidmain(String[]args){

Classc=null;

try{

c=Class.forName("rtti.FancyToy");//必须是全限定名(包名+类名)

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 面试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1