java编程思想读书笔记
【篇一:java编程思想学习笔记】
《java编程思想》学习笔记
1——面向对象和jvm基础
1.java中的4种访问制权限:
(1).public:最大访问控制权限,对所有的类都可见。
(2).protect:同一包可见,不在同一个包的所有子类也可见。
(3).default:包访问权限,即同一个包中的类可以可见。默认不显式指定访问控制权限时就是default包访问控制权限。
(4).private:最严格俄访问控制权限,仅该类本身可见,对外一切类都不可以访问(反射机制可以访问)。
2.面向对象编程中两种对象组合方式——is-a 和 has-a:
(1).is-a组合:一个类继承具有相似功能的另一个类,根据需要在所继承的类基础上进行扩展。
优点:具有共同属性和方法的类可以将共享信息抽象到父类中,增强代码复用性,同时也
是多态的基础。
缺点:子类中扩展的部分对父类不可见,另外如果共性比较少的时候使用继承会增加冗余代码。
(2).has-a组合:has-a组合是在一个类中引用另一个类作为其成员变量。
优点:可扩展性和灵活性高。在对象组合关系中应优先考虑has-a组合关系。 缺点:具有共性的类之间看不到派生关系。
3.多态:
在面向对象编程中,子类中拥有和父类相同方法签名的方法称为子类方法覆盖父类方法,当调用子类方法的某个操作时,不必明确知道子类的具体类型,只需要将子类类型看作是父类的引用调用其操作方法,在运行时,jvm会根据引用对象的具体子类类型而调用应该的方法,这就是多态。
多态的基础是java面向对象编程的晚绑定机制。编程中有如下两种绑定机制:
(1).早绑定:一般在非面向对象编程语言中使用,在程序编译时即计算出具体调用方法体的内存地址。
(2).晚绑定:面向对象编程语言中经常使用,在程序编译时无法计算出具体调用方法体的内存地址,只进行方法参数类型和返回值类型的校验,在运行时才能确定具体要调用方法体的内存地址。
4.java单继承的优点:
相比于c++的多继承,java只支持类的单继承,java中的所有类的共同基类是object类,object类java类树的唯一根节点,这种单继承有以下好处:
(1).单继承可以确保所有的对象拥有某种共同的特性,这样对于jvm虚拟机对所有的类进行系统级的操作将提供方便,所有的java对象可以方便地在内存堆栈中创建,传递参数也变的更加方便简单。
(2).java的单继承使得实现垃圾回收器功能更加容易,因为可以确保jvm知道所有对象的类型信息。
5.选择容器对象两个原则:
(1).容器所能提供不同的类型的接口和外部行为是否能够满足需求。
(2).不同容器针对不同的操作效率不同。
6.类型转换:
java中有两种常见的类型转换:向上类型转换(upcast)和向下类型转换
(downcast):
(1).向上类型转换(upcast):
向上类型转换是将子类对象强制类型转换为父类类型,经典用法是面向对象的多态特性。向上类型转换时,子类对象的特性将不可见,只有子类从父类继承的特性仍然保持可见,向上类型转换时编译器会自动检查是否类型兼容,通常是安全的。
(2).向下类型转换:
向下类型转换是将父类类型强制转换为子类类型,转换过后父类中不可见的子类特性又恢复可见性,向下类型转换时,编译器无法自动检测是否类型兼容,往往会产生类型转换错误的运行时异常,通常不安全。
7.java中5个存放数据的地方:
(1).寄存器(registers):位于cpu内部,是速度最快的存储区,但是数量和容量有限。在java中不能直接操作寄存器。
(2).栈(stack):栈位于通用随机访问存储器 (general random-access memory,ram,内存) 中,通过处理器的栈指针访问,栈指针从栈顶向栈底分配内存,从栈底向栈顶释放内存。栈是仅次于寄存器的速度第二快的存储器,在java程序中,一般的8种 基本类型数据和对象的引用通常存放在栈内存中,不通过new关键字的字符串对象也是存放在栈的字符串池中。栈的优势是,存取速度比堆要快,仅次于寄存器, 栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。
(3).堆(heap):也是位于通用随机访问存储器 (general random-access memory,ram,内存) 中的共享内存池。java的堆是一个运行时数据区,类的对象从中分配空间,凡是通过new关键字创建的对象都存放在堆内存中,它们不需要程序代码来显式的 释放。堆是由垃圾回
收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,java的垃圾收集器 会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。
(4).常量存储器(constant storage):java中的常量是存放在系统内嵌的只读存储器中(read-only memory,rom)的。
(5).非随机存储器(non-ram storage):对于流对象和持久化对象,通常存放在程序外的存储器,如硬盘。
8.javadoc只处理public和protected访问控制权限的文档注释,private和default权限的稳定注释将被忽略。
9.java中赋值运算:
基本类型赋值是直接复制值,赋值操作后,相互不影响。
引用类型赋值是复制引用值,相当于给对象取一个别名,赋值之后两个引用指向同一个引用对象,相互之间有影响。
在java中,向方法传递引用类型参数会改变参数的值,不让参数受到影响的解决方法:在方法内首先先将引用克隆一份,然后操作克隆的对象。
10.移位运算:
左移运算符:将比特位左移指定位数,右边部分补0,左移一位相当于乘2。 右移运算符:
将比特位右移指定位数,如果是正数,左边第一位(符号位)补0,其余位补0,如果是负数,左边第一位补1,其余位补0。右移一位相当于除2。 无符号右移运算符:将比特位右移指定位数,不论是正数或者负数,左边移除位统统补0。
11.java中,比int类型小的原始类型(char、byte、short)进行数算或者位运算时,数据类型首先转换成int类型,然后进行相应的运算。
13.java中的析构函数:
java中没有像c/c++的析构函数,用来销毁不用的对象是否内存空间,只有以下三个方法用于通知垃圾回收器回收对象。
(1).finalize( )只是通知jvm的垃圾收集器当前的对象不再使用可以被回收了,但是垃圾回收器根据内存使用状况来决定是否回收。
finalize()最有用的地方是在jni调用本地方法时(c/c++方法),调用本地方法的析构函数消耗对象释放函数。
(2). system.gc()是强制析构,显式通知垃圾回收器释放内存,但是垃圾回收器也不一定会立即执行,垃圾回收器根据当前内存使用状况和对象的生命周期自行决定是否回收。
(3).runtime.getruntime().gc()和system.gc()类似。
注意:这三个函数都不能保证垃圾回收器立即执行,推荐不要频繁使用。
14.垃圾回收器原理:
(1).引用计数(referencecounting)垃圾回收算法:
一种简单但是速度较慢的垃圾回收算法,每个对象拥有一个引用计数器
(reference counter),当每次引用附加到这个对象时,对象的引用计数器加1。当每次引用超出作用范围或者被设置为null时,对象的引用计数器减1。垃圾回收 器遍历整个对象列表,当发现一个对象的引用计数器为0时,将该对象移出内存释放。
引用计数算法的缺点是,当对象环状相互引用时,对象的引用计数器总不为0,要想回收这些对象需要额外的处理。
引用计数算法只是用来解释垃圾回收器的工作原理,没有jvm使用它实现垃圾回收器。
引用计数的改进算法:
任何存活的对象必须被在静态存储区或者栈(stack)中的引用所引用,因此当遍历全部静态存储区或栈中的引用时,即可以确定所有存活的对象。每当 遍历一
个引用时,检查该引用所指向的对象,同时检查该对象上的所有引用,没有引用指向的对象和相互自引用的对象将被垃圾回收器回收。
(2).暂停复制(stop-and-copy)算法:
垃圾回收器的收集机制基于:任何一个存活的对象必须要被一个存储在栈或者静态存储区的引用所引用。
暂停复制的算法是:程序在运行过程中首先暂停执行,把每个存活的对象从一个堆复制到另一个堆中,已经不再被使用的对象被回收而不再复制。
暂停复制算法有两个问题:
a.必须要同时维护分离的两个堆,需要程序运行所需两倍的内存空间。jvm的解决办法是在内存块中分配堆空间,复制时简单地从一个内存块复制到另一个内存块。
b.第二个问题是复制过程的本身处理,当程序运行稳定以后,只会产生很少的垃圾对象需要回收,如果垃圾回收器还是频繁地复制存活对象是非常低性能的。jvm的解决方法是使用一种新的垃圾回收算法——标记清除(mark-and-sweep)。 一般来说标记清除算法在正常的使用场景中速度比较慢,但是当程序只产生很少的垃圾对象需要回收时,该算法就非常的高效。
(3).标记清除(mark-and-sweep)算法:
和暂停复制的逻辑类似,标记清除算法从栈和静态存储区开始追踪所有引用寻找存活的对象,当每次找到一个存活的对象时,对象被设置一个标记并且不被回收,当标记过程完成后,清除不用的死对象,释放内存空间。
标记清除算法不需要复制对象,所有的标记和清除工作在一个内存堆中完成。 注意:sun的文档中说jvm的垃圾回收器是一个后台运行的低优先级进程,但是在早期版本的jvm中并不是这样实现的,当内存不够用时,垃圾回收器先暂停程序运行,然后进行垃圾回收。
(4).分代复制(generation-copy)算法:
一种对暂停复制算法的改进,jvm分配内存是按块分配的,当创建一个大对象时,需要占
用一块内存空间,严格的暂停复制算法在释放老内存堆之前要求把每个存活的对象从源堆拷贝到新堆,这样做非常的消耗内存。
通过内存堆,垃圾回收器可以将对象拷贝到回收对象的内存堆中,每个内存块拥有一个世代计数(generation count)用于标记对象是否存活。每个内存块通过对象被引用获得世代计数,一般情况下只有当最老的内存块被回收时才会创建新的
【篇二:java编程思想读书笔记】
网格:是一种用于集成或共享地理上分布的各种资源(包括计算机系统、存储系统、通
信系统、文件、数据库、程序等),使之成为有机的整体,共同完成各种所需任务的机制。
mvc(model view controller)一种软件设计典范,用于
java编程思想读书笔记
第一章 对象导论
1.1 对象具有状态、行为和标识。意味着每一个对象都可以拥有内部数据(它们给出了该对象的状态)和方法(它们产生行为),每个对象在内存中都有一个唯一的地址。
所有的对象都是唯一的,但同时也是具有相同的特性和行为的对象所归属的类的一部分。
1.2 类描述了具有相同特性(数据元素)和行为(功能)的对象集合。
1.5 现有的类(方法,属性)合成新的类,称为组合(has-a拥有)。若组合是动态发生的,则称为聚合。
1.11 异常处理就像是与程序正常执行路径并行的、在错误发生时执行的另一条路径。
1.12 线程只是一种为单一处理器分配执行时间的手段。
2.2.1 数据存储的五个地方
1)寄存器:位于处理器内部,处理速度最快,数量有限,自己根据需求进行分配,程序员不能直接控制。
2)堆栈:位于ram(随机访问存储器)中,堆栈指针操作,速度仅次于寄存器。
3)堆:通用的内存池,位于ram,存放所有的java对象。
4)常量存储:通常存放在程序内部,嵌入式时,可选择存放在rom(只读存储器)中。
5)非ram存储:数据存放在程序外。
2.4.1在java中,你所做的全部工作就是定义类,产生那些类的对象,以及法消息给这些对象。
2.5 java的方法决定了一个对象能够接收什么样的信息。方法的基本组成部分包括:名称、参数、返回值和方法体。方法名和参数列表唯一标识出某个方法。方法只有通过对象才能被调用。
2.6.3 当声明一个事物是static时,就意味着这个域或方法不会与包含它的那个类的任何对象关联在一起。所以,即使从未创建某个类的任何对象,也可以调用static方法或访问static域。
一个static字段对每个类来说都只有一份存储空间,而非static字段则是对每个对象斗殴一个存储空间。
4.3 while、do-while、for用来控制循环,也称为迭代语句,语句会重复执行,直到控制作用的布尔表达式得到“假”的结果为止。
4.3.1 while和do-while唯一的区别就是do-while中的语句至少会执行一次。
4.4 foreach语句,常用数组中。可以用于遍历对象。
for(float x: f){}:定义了一个float类型的变量x,继而讲数组f中的每个元素赋值给x。
4.8 switch语句实现多路选择的一种方法,若符合条件要求的整数值,则执行该语句。
5.4 this关键字只能在方法内部使用,表示对“调用方法的那个对象”的引用。
写this都是指“当前对象”,而且它本身表示对当前对象的引用。
this可以调用一个构造器,但不能调用两个。且必须将构造器调用置于最起始处。
除构造器外,编译器禁止在其他任何方法中调用构造器。
5.4.2 static方法就是没有this的方法;在static方法内部不能调用非静态方法,反过来可以;在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。很像全局方法。
5.5 java的垃圾回收机制只知道释放由new分配的内存,无法释放其他特殊的内存,此时,可以用finalize()方法去清理。垃圾回收时,会调用该方法。
如果java虚拟机并未面临内存耗尽的情形,它是不会浪费时间去执行垃圾回收以恢复内存的。
5.6 局部变量:需要赋初值,要是成员变量为基本数据类型,不用赋初值,系统默认一个初值。
在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布在方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。
5.7.2 无论创建多少对象,静态数据只占用一份存储区域。static关键字不能应用于局部变量,它只能作用于域。如果一个域是静态的基本类型域,且也没有对它进行初始化,那么它就获得基本类型的标准初值;如果它是一个对象引用,那么它的默认初始化值就是null。
静态初始化只在必要时刻才会进行。
5.7.3 java允许将多个静态初始化动作组织成一个特殊的“静态子句”,即static{}。
5.8 数组只是相同类型的、用一个标识符名称封装到一起的一个对象序列或基本数据类型。
在编写程序时,无法确定数组里需要多少个元素,可通过random.nextint()方法随机决
定,该方法会返回0到输入参数之间的一个值。 int[] a=new int[ran.nextint(20)];
5.9 枚举:枚举类型的实例是常量。switch是要在有限的可能值集合中进行选择,因此与enum是绝佳组合。
6.java提供访问权限修饰词,以供类库开发人员向客户端程序员指明哪些可用,哪些不可用。
6.2.1 默认访问权限(default)没有任何关键字,通常指包访问权限,即意味着当前的包中的所有其他类对那个成员都有访问权限,但对于这个包以外的其他类,这个成员为private。
6.3 访问权限的常被称为是具体实现的隐藏。
封装:把数据和方法包装进类中,以及具体实现的隐藏。
6.4 类既不可以是private的,也不可以是protected的。
7. 代码重用的两种方式:组合和继承。
想调用一个带参数的基类构造器,就必须用关键字super显示地编写调用构造器的语句,并且配以适当的参数列表。
7.8 一个既是static又是final的域只占据一段不能改变的存储空间。
8. 多态不但能够改善代码的组织结构和可读性,还能够创建可扩展的程序—--即无论在项目最初创建还是在需要添加新功能时都可以“生长”的程序。
9.2接口中显式地将方法声明为public,即使不声明,默认的也是public。
9.6 接口最吸引人的原因之一就是允许同一个接口具有多个不同的具体实现。
9.9 接口是实现多重继承的途径,而生成遵循某个接口的对象的典型方式就是工厂方法设计模式。
10. 可以将一个类的定义放在另一个类的定义内部,这就是内部类。
10.2 内部类不仅是一种名字隐藏和组织代码的模式;当生成一个内部的对象时,该对象与制造它的外围对象之间就有了一种联系,所有它能访问其外围对象的所有成员,而不需要任何特殊条件;内部类还拥有其外围类的所有元素的访问权。
10.4 当内部类向上转型为一个接口的时候,内部类就有用武之处了。
10.7 若不需要内部类对象与外部类对象之间有联系,则可将内部类声明为static,也称嵌套类。意味着,要创建嵌套类的对象,并不需要其外围类的对象;不能从嵌套类的对象中访问非静态的外围类对象。普通的内部类不能有static数据和static字段,也不能包含嵌套类。
10.8 每个内部类都能地继承自一个接口的实现,无论外围类是否已经继承了某个接口的实现,对于内部类都没有影响。
【篇三:java编程思想读书笔记】
第2章 万事万物皆对象
(源码网整理:www.codepub.com)
一.所有对象都必须由你建立
1. 存储在哪里
1. 寄存器:我们在程序中无法控制
2. stack:存放基本类型的数据和对象的reference,但对象本身不存放在stack中,而是存放在heap中
3. heap:存放用new产生的数据
4. static storage:存放在对象中用static定义的静态成员
5. constant storage:存放常量
6. non-ram:硬盘等永久存储空间
2. 特例:基本型别
基本类型数据存放在stack中,存放的是数据。而产生对象时,只把对象的reference存放在stack中,用于指向某个对象,对象本身存放在heap中。
3. java中的数组
当你产生某个存储对象的数组时,真正产生的其实是存储reference的数组。引数组建立后,其中的每一个reference都会被自动设为null,表示“不指向任何对象”。
二.建立新的数据型别:class
1. 数据成员和函数
1.1 基本成员的缺省值
1) 当class的某个成员属于基本型别时,即使你没有为它提供初值,java仍保证它有一个缺省值。
2) 只有当变量身份是“class内的成员时,java才保证为该变量提供初值。
三.函数(mehtods),引数(arguments),返回值(return values)
1. 引数列
当引数传递的是对象时,传递的是对象的reference。
四.注解用内嵌式文档
java提供两种注解风格:/*xxxx*/、//xxxx
第3章 控制程序流程
一.使用java运算符
1.关系运算符
1.) 当对两个对象运用关系运算符进行比较时,比较的是object reference,如: integer n1 = new integer(3);
下载源码就到源码网,www.codepub.com
integer n2 = new integer(3);
system.out.println(n1==n2);
结果为false,因为两个object reference(n1和n2)值是不同的
2) quals()的缺省行为也是拿referenct来比较。不过java中的class覆写了equals方法,如:
integer n1 = new integer(3);
integer n2 = new integer(3);
system.out.println(n1.quals(n2));//值为true
2. 逻辑运算符
1) 只能将and、or、not施用于boolean值身上。如果逻辑运算符两边的值存在non-boolean值,将会出错,如:
int test1 = 1;
system.out.println((test 12);//编辑出错,test是non-boolean值
3. 位移运算符
如果所操作的位移对象是char、byte、short,位移动作发生之前,其值会先被晋升为int,运算结果会是int。
二.流程控制
1. 迭代(iteration)
1.1 逗号运算符
逗号运算符只能用于for循环的控制表达式中的initialization和step两部分中,如:for(int i下载源码就到源码网,www.codepub.com
=0, j=i+1; i5; i++, j=i*2)
1.2 break和continue
break表示退出循环;continue表示退出本次循环,回来循环起始位置。
1.3 label
label只有放在迭代语句之前才起作用,在label和迭代语句之间插入任何语句都不会起作用。
2. switch
switch中的选择器必须是int或char型,如:
float i = 2;
switch ( i )//将出错,因为i不是int或char之一
3. 计算细节
1) 从float或double转为整数值,总是以完全舍弃小数的方式进行。
4. math.random()的输出范围是[0, 1]。
第4章 初始化和清理
一.以构造函数(constructor)确保初始化的进行
如果某个class具备构造函数,java便会在对象生成之际,使用者有能力加以操作之前,自动调用其构造函数,于是便能名确保初始化动作一定被执行。
二.函数重载(method overloading)
1. 区分重载函数
下载源码就到源码网,www.codepub.com
由于只能从函数名和函数的引数列来区分两个函数,而重载函数具有相同的函数名称,所以每个重载函数都必须具备独一无二的引数列。
2. default构造函数
1) default构造函数是一种不带任何引数的构造函数。如果你所开发的class不具任何构造函数,编译器会自动为你生成一个default构造函数。
2) 如果你自行定义了任何一个构造函数(不论有无引数),编译器就不会为你生成default构造函数。
3) 如果定义了一个class,如
class bush{
bush(int i){}
}
当想用new bush();来产生class的实例时,会产生错误。因为在定义class时已定义了
构造函数,所以编译器就不会为class生成default构造函数。当我们用new bush()来产生实例时,会尝试调用default构造函数,但在class中没有default构造函数,所以会出错。如: class sundae
{
sundae(int i) {}
}
public class icecream
{
public static void main(string[] args)
下载源码就到源码网,www.codepub.com
{
//sundae x = new sundae();会编译出错,无构造函数sundae()
sundae y = new sundae(1);
}
}
*:在定义一个class时,如果定义了自己的构造函数,最好同时定义一个default构造函数
3. 关键字this
1) this仅用于函数之内,能取得“唤起此一函数“的那个object reference。
2) 在构造函数中,通过this可以调用同一class中别的构造函数,如
public class flower{
flower (int petals){}
flower(string ss){}
flower(int petals, sting ss){
//petals++;调用另一个构造函数的语句必须在最起始的位置
this(petals);
//this(ss);会产生错误,因为在一个构造函数中只能调用一个构造函数
}
}
**:1)在构造调用另一个构造函数,调用动作必须置于最起始的位置
下载源码就到源码网,www.codepub.com
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuo9.cn 版权所有 赣ICP备2023008801号-1
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务