java 编程思想 笔记_java编程思想笔记

第一章:对象导论

1.1伴随多态的可互换对象

面向对象程序设计语言使用了后期绑定的概念。当向对象发送消息时,被调用的代码直到运行时才能确定。也叫作动态绑定。

编译器确保被调用的方法的存在,并对调用参数和返回值执行类型检查(java是强类型的语言,无法提供此类保证的语言称为弱类型的),但是并不知道将被执行的确切代码。

在某些语言中,必须明确地生命希望某个方法预备后期绑定属性所带来的灵活性(C++使用virtual关键字实现的)。在这些语言中,方法默认不是动态绑定的。而java中,动态绑定是默认行为(java中除了使用static,final,private方法外,其他方法都是动态绑定的),不需要添加额外的关键字来实现多态。

把导出来类看做是他的基类的过程称为向上转型(upcasting)

1.2单根继承结构

在java中(事实上还包括除C++以外的所有OOP语言),所有的类最终都继承自单一的基类,这个终极基类的名字就是Object.

单根继承结构的好处:

在单根继承结构中所有对象都具有一个公用接口,所以他们归根到底都是相同的基本类型

单根继承结构保证所有对象都具备某些功能

单根继承结构使垃圾回收的实现变得容易,二垃圾回收正式相对C++的重要改进之一。由于所有对象都保证具有其类型信息,因此不会因无法确定对象的类型而陷入僵局。这对于系统级操作(如异常处理)显得尤其重要,并且给编程带来了更大的灵活性。

1.3对象的创建和生命周期

对象的数据位于何处(作用域)

将对象置于堆栈或静态存储区域来实现。这种方式将存储空间分配和释放置于优先考虑的位置,某些情况下这样控制非常有价值。但是,也牺牲了灵活性)

第二种方式被称为堆(heap)的内存池中动态地创建对象。这种方式中,知道运行时才知道需要多少独享,他们的生命周期,以及他们的具体是什么。

java完全采用动态内存分配方式(基本类型是一种特例)。每当想要创建对象时,就要使用new关键字来构建对象的动态实例。

对象生命周期

java的垃圾回收器被设计用来处理内存释放问题

第二章 一切都是对象

2.1特例:基本类型

基本类型是一个并非是引用的“自动”变量。这个变量直接存储“值”,并置于堆栈中,因此使用更高效,java的基本类型所占存储空间大小不随机器硬件架构的变化而变化。这种所占存储空间大小的不变性是java程序比其他大多数语言编写的程序更具有可移植性的原因之一。

基本类型

大小

包装器类型

boolean

-

Boolean

byte

8bits

Byte

char

16bits

Character

short

16 bits

Short

int

32 bits

Integer

float

32 bits

Float

long

64 bits

Long

double

64 bits

Double

void

-

Void

所有数值类型都有正负号

boolean类型所占存储空间的大小没有明确指定(要看具体虚拟机的实现),仅定义为能够取字面值true或false.

2.2java中的数组

java确保数组会被初始化。而且不能在它的范围之外被访问。这种范围查找,是以每个数组上少量的内存开销以及运行时的下标检查为代价的。

《深入理解Java虚拟机》:

Java 语言中对数组的访问比C/C++相对安全是因为:如有一维数组,其元素类型为 mypackage.MyClass,则虚拟机会自动生成一个直接继承于java.lang.Object的子类[Lmypackage.MyClass,创建动作由字节码指令newarray触发。这个类代表了一个元素类型为mypackage.MyClass的一维数组,数组中应有的属性和方法(用户可直接使用的只有被修饰为public的length属性和clone()方法)都实现在这个类里。Java语言中对数组的访问比C/C++相对安全就是因为这个类封装了数组元素的访问方法(准确地说,越界检查不是封装在数组元素访问的类中,而是封装在数组访问的xaload、xastore字节码中),而C/C++直接翻译为对数组指针的移动。

数组对象,实际就是一个引用数组,每个元素会被初始化为null.

基本数据类型的数组,编译器会将这种数组所占的内存全部置为零

在java中,检查到数组越界是会抛出java.lang.ArrayIndexOutOfBoundsException异常。

第8章 多态(Polymorphism)

8.2 域与静态方法

域是不具有多态性的,只有普通的方法调用是多态的。如果直接访问某个域,这个访问就将在编译期进行解析,即域是静态解析的。

如下,当Sub对象转型为Super引用时,任何域访问操作都将由编译器解析,因此不是多态的。Super.field和Sub.field分配了不同的存储空间。这样,Sub实际上包含两个称为field的域:它自己的和它从Super处得到的。

class Super{

public int field = 0;

public int getField(){return field;}

}

class Sub extends Super{

public int field = 1;

public int getField(){return field;}

public int getSuperField(){return super.getField();}

}

public class FieldAccess{

public static void main(String[] args){

Super sup = new Sub(); // Upcast

System.out.println("sup.field = " + sup.field + ". sup.getField() = " + sup.getField());

Sub sub = new Sub();

System.out.println("sub.field = " + sub.field + ". sub.getFiled() = " + sub.getField() + ". sub.getSuperField() = " +     sub.getSuperField());

}

}

/** Output:

* sup.field = 0. sup.getField() = 1

* sub.field = 1. sub.getFiled() = 1. sub.getSuperField() = 0

*/

静态方法也是不具有多态性的,如前文所述,静态方法是与类,而非与单个的对象相关联的。

8.3 构造器内部的多态方法的行为

如果在构造器内部调用正在构造的对象的某个动态绑定方法,由于动态绑定是在运行时才决定的,而此时,该对象还正在构造中,所以它不知道自己属于哪个类(父类还是自己),并且方法所操纵的成员可能还未进行初始化,这可能会产生一引起难于发现的隐藏错误。

public class PolyConstructors {

public static void main(String[] args){

new RoundGlyph(5);

}

}

class Glyph{

void draw(){

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

}

Glyph(){

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

draw();

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

}

}

class RoundGlyph extends Glyph{

RoundGlyph(int r){

draw();

radius = r;

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

}

private int radius = 1;

void draw(){

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

}

}

Glyph() before draw()

RoundGlyph.draw(), radius = 0

Glyph() after draw()

RoundGlyph.draw(), radius = 1

RoundGlyph.RoundGlyph(), radius = 5

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值