第一章对象导论(Java的几个重要部分)

访问控制的目的:

1.权限控制 2.类创建者修改某些实现而不会影响类使用者

代码复用的方式:

1.继承 2.组合(composition UML中实心菱形+实线表示)

继承

(UML中空心三角+实心线表示)

基类与子类行为不同的产生方式

  1. 为子类新增方法
  2. 在子类覆盖(overriding)基类的原来的方法

两种关系

  1. 是一个 is-a 纯粹替代(子类和父类接口方法完全相同,子类的接口 方法可能在父类存在,反之亦然)
  2. 像是一个(子类和父类不完全相同,子类的接口 方法可能在父类不存在,下图为is-like-a的例子)

多态:

父类引用指向子类对象 ClassParent classA = new ClassChild(); 也就是将子类泛化成父类类型 在新增一个继承父类的子类类型时,可以轻松替换掉原来的子类类型,程序更新维护便利,在实际classA调用方法的时候编译器并不知道要调用的代码在什么地方,是在运行时才知道调用子类的对应方法的,这也称为后期绑定。

向上转型:

将子类看作是基类的过程称为向上转型(upcasting)

方向相反则是向下转型,向下转型可能导致ClassCastException,因为就像是一个形状不一定是圆,它也可能是矩形或者三角形.而参数化类型:泛型正是为此而生

Java 单根继承的好处:

多重继承很灵活但是复杂,而单根继承相对简单,效率更高。单根继承类型是确定的,这样优化了垃圾回收;垃圾回收往往因为不确定的类型而陷入僵局。

Java的容器列举

List(存储序列)Map(关联数组,建立Key value关系)Set(内容不可重复,实现基于map)队列 树 堆栈等

Java的内存分配与垃圾回收

C++对象的生命周期和存储位置可以在编写程序时决定,但是这样必须知道对象的确切数量生命周期和类型,在解决一般化或者特别复杂的问题时不够灵活。
Java则在堆(heap)内存池中动态创建对象。知道运行时才知道需要多少对象,生命周期如何,具体是什么类型。只有程序运行到相关代码行才能确定这一切。如果需要一个对象,可以随时在堆中创建,这是因为存储空间在运行时时动态管理的,也因此一般比在堆栈中创建和销毁对象需要更多的时间。
动态方式在创建对象时具有灵活性,所以适用于复杂系统。但是效率可能就没有C++高了。
因为Java采用了动态堆上分配内存的机制,因此Java垃圾回收可以自动回收,而像C++手动堆栈分配内存就没法做到自动回收,程序员手动回收时则容易出现遗漏后者错误

异常处理

在从错误状态进行可靠恢复的途径

并发编程

优点:多处理器同时执行任务,效率高 缺点:共享资源时存在隐患
网络编程
客户端编程与服务器编程

本章主要讲述Java的一些重要特点

第二章 一切都是对象

Java程序的存储位置

(书中总结的很好)

寄存器:

运算速度最快,但是数量有限,在Java中是不可直接控制的。从程序中无法感觉寄存器的存在

堆栈:

位于RAM(随机访问存储)中,多用于存储对象的引用,依靠指针的上下移动来工作。指针上移,便是释放一个对象,指针下移,表示分配一个新内存。因为需要上下移动指针,所以Java系统需要知道存储在堆栈中所有对象的确切生命周期。对战的速度仅次于寄存器。注意堆栈中存储了对象的引用但没有将实际对象存储在这里

堆:

也位于RAM中,用于存放Java对象。堆与堆栈的区别主要在于1.他们存储的内容不同2.堆不需要也不知道堆中存储的数据需要存活多久。当使用new新建一个对象时,堆中自会给其分配内存。因此相比于堆栈,堆中的内存分配更加灵活,但是因为这种灵活,也需要付出代价:堆中的内存分配和释放需要更多的时间

常量存储:

根据不同系统而不同,有的系统将常量存放在程序代码内部;而有的系统则会将常量与其他部分分离,在此情况下,可以将常量存放于ROM(只读存储器)–典型的例子是字符串常量池

非RAM存储:

数据可以脱离程序而存在,此类的两个典型是流对象和持久化对象。流对象通常发生在一个机器与另一个机器的数据传输,对象被转化成字节流或者字符流传输给另外一个对象。持久化对象则被存储与磁盘,需要时则可以将他们解析和转换成基于RAM,可恢复的常规的程序对象。
特例,基本类型的存储
因为使用new创建对象需要在堆栈生成一个引用,在堆中动态分配内存,对象如果比较小,往往效率不高。8大基本类型在堆栈中创建的变量存放的不是引用而直接存放值,这样就不必在堆中分配内存,因此基本类型的创建更为灵活。

当然基本数据类型都有与之对应的包装类,而包装类的创建对象的形式则和普通对象的创建方式一样。比如
Integer I = new Integer(10);
User user = new User();
在堆栈和堆中创建变量,分配内存的形式是一样的

数组的存储

数组在C与C++中是一个连续的内存块,而在Java中,创建数组则意味着创建了一个引用数组,并且每一个引用初始化为null
变量的作用域由花括号决定。

对象的作用域:

举个例子
{
String s = new String(“aaa”);
}
其中变量s的作用域在后花括号之后就消失了,但是s所指向的String对象仍然存在于堆栈中。在C++中,这样的对象积累起来,会导致内存占用,这会引起内存泄漏但是Java由自己的垃圾回收机制,不需要程序员手动处理类似问题,这样就避免嘲笑我忘记释放内存而产生问题。

变量的初始化

类的字段可以不进行初始化,Java会有一些默认初始化

类的字段如果是一个引用,则没有初始化,其值默认初始化为null.
而方法中的变量必须初始化,若非如此,Java会提示错误 变量没有初始化。

变量的区分

使用包名区分

使用其他构建

运用import导包

static关键字

类的static变量对于该类的所有对象来说只存在一个实例(static字段堆每个类来说只有一份存储空间),该变量可以直接使用类名获取其值,也就是说即使没有创建对象,也可以调用该变量。被static修饰的方法和变量在一些文献中也叫类方法和类变量。

编译运行的条件

1.安装JDK并配置好环境变量(目的是能找到java和javac两个命令)
2.javac Xxx.java
3.java Xxx

注释和嵌入式文档(关于如何写注释)

常见的单行 多行注释不需多说,本小节主要说的是Javadoc这个注释提取工具,在java文件中注释以一定格式编写,则使用javadoc可以提取注释并生成另外的文档,一般可以使用浏览器打开类似的文档,撰写注释是务必遵守一些语法,还会使用到一些html标签和@开头的javadoc标签(@See @link之类),在实际中其实用的比较少,但是我们可以看到我们使用的JDK的注释中确实出现类似描述的东西。由于用的比较少,就不详述了。

编码风格

驼峰式为主

本章主要讲述要创建第一个Java程序需要的要素,比如项目构建需要创建包名,需要导包,需要创建方法,变量,使用静态方法,如何注释并通过javadoc生成html文档等等

第三章 操作符(有些简单的操作符就略过了)

别名机制问题引入

其实就是引用传递的问题,问题出现在赋值和方法调用上
比如

public class Book {public Book(String name) {super();this.name = name;}String name;private void changeString(String s) {s = "zzz";}private void changeString(Book book) {book.name = "zzz";}public static void main(String [] args){Book book1 = new Book("Java");Book book2 = new Book("Android");System.out.println(book1.name);System.out.println(book2.name);book1 = book2;//赋值产生的引用传递  这句是问题关键book1.name = "Java Script";System.out.println(book1.name);System.out.println(book2.name);book2 = book1;book1.name = "Python";System.out.println(book1.name);System.out.println(book2.name);System.out.println();//参数传递时的引用传递String s = "abc";book1.changeString(s);//调用changeString方法System.out.println(s);String bookName = "C++";Book book = new Book(bookName);book.changeString(book);//调用changeString(Book)方法System.out.println(bookName);System.out.println(book.name);//核心: 基本类型赋值和方法调用都不会发生引用传递,都是拷贝值,只有引用类型的变量才有这两个问题。//这里应该时问题的引入,不理解也没关系,第六章应该会有详述}
}

输出

Java
Android
Java Script
Java Script
Python
Pythonabc
C++
zzz

关于运算符

其优先级不需要死记硬背,有时候不记得可以使用括弧,而且这样程序的可读性更高。
对于++i --i i++ i–之类的操作符也很简单,不赘述

等价性

基本类型的等价性

直接用== !=判断即可,比如

 public static void main(String[] args) {String string1 = "sd";String string2 = "sd";System.out.println(string1 == string2);}

输出true

引用类型的等价性

对于Java已经定义好的引用类型(如Integer String Boolean)大多数可以使用equals来判断内容是否相等

 public static void main(String[] args) {String string1 = new String("sd");String string2 = new String("sd");System.out.println(string1 == string2);System.out.println(string1.equals(string2));Boolean boolean1 = new Boolean(false);Boolean boolean2 = new Boolean(false);System.out.println(boolean1 == boolean2);System.out.println(boolean1.equals(boolean2));Integer integer1 = new Integer(15);Integer integer2 = new Integer(15);System.out.println(integer1 == integer2);System.out.println(integer1.equals(integer2));}

输出

false
true
false
true
false
true

可以看到 “== ”用在引用类型上,输出结果可能与想象的不同,这是因为对于引用类型,“”判读的是 对象的引用是否相等,当我们使用new创建对象时,java往往分配不同的堆栈和堆空间给不同的对象,因此对于引用类型,使用“”判断往往返回false。
但并不是只要是引用类型,只要使用equals就可以判断其内容是否等价。当比较对象类型是自定义类型时,需要我们覆盖Object的equals方法才可以正确比较,否则调用equals方法会默认调用Object的equals方法,而它的实现就是使用“==”来比较,这一点在第17章将会详述。

逻辑操作符

与或非(&& || !)比较简单,就略过了,但是书中也讲述了&&和& 以及|| 和|的关系,实际应用时,似乎|和&很少使用,关键词是短路,简单,略过。

直接常量

此处没搞明白,说是直接变量或许更好?这里说的最多的一个是定义数字类型时加前缀后缀的问题,这个用的其实很少。另外一个是“窄化转型”,在本章后面有讲述。

指数计数法

这用的也特别少,这里Think in Java还是很严谨的,详述了Java中e与科学自然e的区别。

按位操作符

这个用的也比较少,一共四种 按位与& 按位或| 按位非~ 按位异或^,他们和逻辑操作符极为类似。
一个例子

 public static void main(String[] args) {int i = 1 + 4 + 16 + 64;int j = 2 + 8 + 32 + 128;System.out.println("i = " + Integer.toBinaryString(i));System.out.println("j = " + Integer.toBinaryString(j));System.out.println("i & j = " + Integer.toBinaryString(i & j));System.out.println("i | j = " + Integer.toBinaryString(i | j));System.out.println("i ^ j = " + Integer.toBinaryString(i ^ j));System.out.println("~i = " + Integer.toBinaryString(~i));System.out.println("~j = " + Integer.toBinaryString(~j));}

结果

i =   1010101
j = 10101010
i & j = 0
i | j = 11111111
i ^ j = 11111111
~i = 11111111111111111111111110101010
~j = 11111111111111111111111101010101

移位操作符

分左移位操作符<< 右移位操作符>> 无符号右移>>> 这个我也不经常使用,其他书籍资料中讲述位运算对于机器来说,其速度比普通的加减乘除快,所以很多地方为了提高运算速度使用移位,比如左移一位一般是2 两位4,三位*8……
这里的移位和按位操作符结合起来,还是很复杂的,但其实用的不多,至于掌握到什么程度,就看个人需要了。

三元操作符 ? :

就是if else的简化版,只能由一个else,看起来代码简洁些。在Android studio中,如果可以使用但没有使用三元操作符的地方会有警告,但书中以及个人也觉得if else的逻辑可读性更高,何时使用三元操作符就看个人了

字符串拼接 +

这个用的就多了,不过也很简单,就是如果一个表达式以字符串起头,后面所有操作数都会自动转成字符串类型
例子

 public static void main(String[] args) {int x = 1;int y = 3;String string = "string";System.out.println(x + y + string);System.out.println(x + string + y);System.out.println(string + x + y);}

输出

4string
1string3
string13

关于Java数字类型的转换

byte8位 short16位 int32位 long64位 float32位 double64位
char16位
日常赋值和计算时会有些类型的转换,这种情况发生在
1.不同类型的变量之间的赋值
2.不同类型的变量之间的运算
第一点例如:

     int x =1;float y = 2.02f;System.out.println(x +" "+ y );y = x;System.out.println(x +" "+ y );y = (float)x;//强制转换其实是不必要的,会自动转换System.out.println(x +" "+ y );

第二点比如int类型与float类型运算,结果会是float类型
float类型与double类型运算,结果会是double类型

类型提升和强制转换

将int值赋值给float变量,值会自动转型成float类型,就像执行了强制转换,这种自动的转换在本书中称为
类型提升,即将一个小容器里的东西放到大容器中。但反过来则不行
将float值赋值给int变量,会报错,除非加上强制转换,可以理解为Java认为这样做会丢失精度,是不安全的,需要使用者自己知道。这就相当于将大容器的东西放到小容器,小容器有可能放不下,那么只能把物体裁小(精度丢失),才能放入小容器,就出现了截尾。
比如将29.7赋值给int值,则最后的值是29
想要使用四舍五入要使用Math类的round方法

关于操作符的建议

1.如果不确定操作符的运算顺序,就使用括弧,这样可以提高可读性和确保代码正确性
2.(个人想法,不是书中建议)如果没有必要,尽量避免不同类型数值之间的运算,虽然类型转换有一定的规律可循,但是我们应当避免无意的错误或者精度丢失。这样的错误往往是难以发现的。

操作符小结

char byte short运算时有时会被操作符进行类型提升(转化成int值)之后需要自行窄化(强制转换成原来的类型,可能信息丢失)
相同类型的数据进行运算时要注意可能的超出范围
bool类型的数据在java中的功能很有限,很多在c c++中可以进行的操作在Java中是行不通的

Think in Java第四版 读书笔记1相关推荐

  1. Think in Java第四版 读书笔记10 第16章 数组

    Think in Java第四版 读书笔记10 第16章 数组 数组和容器很像 但他们有一些差别 16.1 数组为什么特殊 数组与容器的区别主要在效率和存储类型 效率:数组是简单的线性序列 使得数组的 ...

  2. Think in Java第四版 读书笔记9第15章 泛型

    Think in Java第四版 读书笔记9第15章 泛型 泛型:适用于很多很多的类型 与其他语言相比 Java的泛型可能有许多局限 但是它还是有很多优点的. 本章介绍java泛型的局限和优势以及ja ...

  3. Think in Java第四版 读书笔记2

    习题答案 http://greggordon.org/java/tij4/solutions.htm 第四章 控制流程(本节很简单,很多内容掠过) if else if else if while d ...

  4. Think in Java第四版 读书笔记7第13章 字符串

    本章内容 1.string的基本使用 2.string拼接符 + 3.Object方法toString 4.String的常用方法 5.String的格式化输出 6.正则表达式 13.1 不可变字符串 ...

  5. Think in Java第四版 读书笔记6第12章 异常处理

    12.1 概念 异常可以将"在正常时候执行的代码"和"发生错误时的代码"相分离,达到结构清晰的目的. a.受检查异常checkedException 编译器强制 ...

  6. Think In Java第四版读书笔记

    02-一切都是对象 将一切都"看作"对象,操纵的标识符实际是指向一个对象的"句柄". 可将这一情形想象成用遥控板(句柄)操纵电视机(对象). String s; ...

  7. Think in Java第四版 读书笔记8第14章 类型信息(RTTI与反射)

    Java如何在运行时识别对象和类的信息? 1.RTTI(Run-time type information) 它假定我们在编译时已经知道了所有类型 2.反射 它允许我们在运行时发现和使用类的信息 14 ...

  8. Think in Java第四版 读书笔记5第11章

    第十一章 持有对象(主要讲容器类) 概要 通常程序中我们需要一些容器来存储对象或者对象的引用 在java中承担这一责任的是数组和容器类 数组VS容器类 数组存在一个缺陷:长度固定不够灵活 而容器类则没 ...

  9. Think in Java第四版 读书笔记4第九章第十章

    第九章 抽象类与接口 9.1抽象类和抽象接口 抽象类可以有具体实现的方法(并不是所有方法都是abstract的)(比如这样 abstract void test3();) 子类继承抽象类要么要实现(覆 ...

最新文章

  1. 基于shell脚本比较数字大小
  2. why is pc important for university students?
  3. Delphi应用程序的调试(二)使用断点
  4. 图像分类数据库_图像分类器-使用僧侣库对房屋房间类型进行分类
  5. .NET Framework3.0答疑
  6. OffsetIndex和TimeIndex分析
  7. 12006.eeprom之M24C02
  8. python3.5以及scrapy,selenium,等 安装
  9. [Java] 蓝桥杯ADV-171 算法提高 身份证号码升级
  10. Windows7 64位下SDK Manager.exe无法运行问题解决方法
  11. java 中文数字排序_java 中文数字排序方法
  12. 直播视频网站源码,静态时钟
  13. mysql完整性实验报告_MySQL数据库技术实验报告模板
  14. VB.net 调用FFmpeg简单处理视频(类库——6)
  15. 牙疼不是病疼起来真要命!教你几个止疼小偏方
  16. uniapp使用IPA苹果支付
  17. 打通WordPress和微信公众号
  18. (附源码)计算机毕业设计SSM智慧工地管理系统
  19. 《卓有成效的管理者》——学习心得(七)
  20. artemis mq配置开机启动 (centos7)(artemis Init Script)

热门文章

  1. 简单粗暴地理解js原型链--js面向对象编程
  2. python的高阶函数
  3. 符号扩展和无符号扩展
  4. PYTHON 自动化学习之路
  5. ACM题目————食物链
  6. jQuery延迟对象deferred的使用
  7. java中throws和throw的区别和用法
  8. Openjudge-计算概论(A)-计算三角形面积
  9. python sublime 提示补全_【原创】Sublime+Verilator建立强大的verilog编写环境
  10. oopc——5.多态