java编程思想 第二章笔记
1.1 用引用操作的对象
java中的一切被视为对象,但是我们操纵的标识符实际上是对象的一个引用(reference)。
所拥有的引用并不一定和一个对象关联起来:
String s; //这里只创建了引用,没有对象
String t="asdf"; //没有指向的引用是不安全的,所以创建时便进行初始化
作者在开始时认为,java的引用,在语法上更接近C++的引用而不是指针,并且用‘句柄’(handle)来称呼他,在后来改回‘引用’。同时表述了对于
任何事物都是'按值传递'
说法的看法(我竟然没看懂到底表述了啥,当然你可能也没看懂我想表述啥)
纪念重新翻开《java编程思想》再次开始思考的第一个问题:
值传递和引用传递
当第一遍粗略翻过第二章内容的时候,我根据明面总结出来的结论是
基本数据类型为值传递,引用数据类型为引用传递
多么简单粗暴,明了易懂而又美好的结论,但是混了这么多年,我本能也知道这个说法有问题,只是一直没去深究他。这一次,好好看一看!
学习的第一步:
马仔同学为我们提供了一个例子
public class ValueOrRef {
public static void main(String[] args) {
Person zhangsan = new Person("ZHANG San");
changePerson(zhangsan);
zhangsan.printName();
//2,然会,最后我们所得到的输出依然是张三
}
public static void changePerson(Person person){
person = new Person("LI Si");
//1,如果是按照我们开始的传递引用理解,在这一步当中,引用被赋予了新的对象(李四)
}
}
class Person {
String name = "default";
public Person(String name) {
this.name = name;
}
public void changeName(String name){
this.name = name;
}
void printName() {
System.out.println(this.name);
}
}
所以引用传递在这里应当看作是实际引用地址的值传递
,改变指向对象属性时,两者改变时同一个对象,当改变引用指向的对象(引用地址)时,两者不再统一指向一个对象。
第一次关于引用传递和值传递的思考结束
1.2 必须由你创建所有对象
程序运行时对象存储的位置
1,寄存器 ,位于处理器内部,最快的存储区,但是数量有限,按需分配不能直接进行控制,C和C++可以向编译器建议寄存器的分配方式
2,堆栈 ,通常为于RAM(随机访问存储器),通过堆栈指针可以从处理器获得直接支持,堆栈指针向下移动,分配新内存,向上移动,释放内存。仅次于寄存器,创建程序时,java系统必须知道存储在堆栈中的所有项的确切生命周期,以便移动堆栈指针,这限制了程序的灵活性,所以虽然某些Java数据存储在堆栈中——特别是对象引用,但是java对象并不存储于其中。
3,堆 ,一种常规用途的内存池(也在RAM区域),其中保存了Java对象。和堆栈不同,“内存堆”或“堆”(Heap)最吸引人的地方在于编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间。因此,用堆保存数据时会得到更大的灵活性。要求创建一个对象时,只需用new命令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保存。当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会花掉更长的时间!
4,常量存储 ,通常存储于代码内部,嵌入式系统中会存储于ROM(只读存储器中)中,避免被修改
说来惭愧,看着这一段的字有点多,就准备上网复制一下,然后在网上搜了一下发现了一个GitBook上的一个版本
image.png这里用到的还是‘句柄’这个词而非‘引用’,说明这是老版本的TIJ,和我手头版本的对比,他多了一个静态存储
,指类变量的存储。
神奇,打开我们的搜索器:
java中堆栈(stack)和堆(heap)(还在问静态变量放哪里,局部变量放哪里,静态区在哪里.....进来)
呃。。。。。。这个问题,等我们看完JVM有个更深入的理解再来说吧。
特例,基本类型
基本类型:一个非引用的变量,这个变量直接存储值,并置于堆栈中,因此更加高效。
image.png基本类型会在栈中创建,而对于对象类型,对象在堆中创建,对象的引用在栈中创建,基本类型由于在栈中,效率会比较高,但是可能存在内存泄漏的问题
基本类型 | 大小(字节) | 默认值 | 封装类 |
---|---|---|---|
byte | 1 | (byte)0 | Byte |
short | 2 | (short)0 | Short |
int | 4 | 0 | Integer |
long | 8 | 0L | Long |
float | 4 | 0.0f | Float |
double | 8 | 0.0d | Double |
boolean | - | false | Boolean |
char | 2 | \u0000(null) | Character |
void | - | - | Void |
数值类型全都是有符号(正负号)的,所以不必费劲寻找没有符号的类型。
基本数据类型拥有自己的“包装器类”(wrapper)类,这让我们可以在堆中创建一个非基本对象,用来标识对应的基本类型
为什么需要封装类?
因为泛型类包括预定义的集合,使用的参数都是对象类型,无法直接使用基本数据类型,所以Java又提供了这些基本类型的封装类。
void的封装类主要是用来干什么的,这个有啥用?
我们暂且就当:boolean类型占了单独使用是4个字节,在数组中又是1个字节
不看基本数据类型,不看位运算,不知道自己涝。虽说天天CRUD这些东西也用不大到,但是该拾起来的还是要拾的。慢慢来吧。
关于char中英文和数字的转化(ASCII )关于编码的基础补充
Java中的ASCII、Unicode和UTF-8字符编码集
关于最大时值最小值的问题,额。。。。。。慢慢来!
高精度数字
//BigInteger 支持任意精度的整数
//BigDecimal 支持任意精度的定点数
java中的数组
创建数组时,实际上时创建了一个引用数组,并且每个引用都会自动被初始化为一个特定的值,该值拥有自己的关键字null~~
创建基本类型数据类型的数组,编译器会保证这种数组的初始化,因为它会将这种数组所占的内存全部置0
boolean和char会是什么
应该是基本数据类型的默认值,boolean默认为了false,但是char的默认值感觉有点怪怪的(\u0000(null)),这个要如何理解
搜索引擎:
答案1:
image.png
答案2:
image.png
照着第二个答案写了个小测试:
public class Base {
private static char a ;
public static void main(String[] args) {
System.out.println(a=='\u0000'); //true
char s = '\u0000';
Character character = s;
System.out.println(character=='\u0000');//true
System.out.println(character==null);//false
}
}
好吧,可能是我的理解有偏差,并不能完全当作null来使用,应该还是像第一种说法,这个null就是Unicode里的null。
并且在char的封装类Character类中,最小值就是'\u0000'
public static final char MIN_VALUE = '\u0000';
1.3 永远不要销毁对象
作用域(scope)
决定了其内定义的变量名的可见性和生命周期,作用域由花括号决定
{
int x = 12;
{
int x = 95;//java中不允许如此操作
}
}
对象的作用域
引用会在作用域的终点消失,但是引用指向的对象仍继续占据内存空间。
java的垃圾回收器,会监视用new创建的所有对象,并在对象不会再被引用时,释放对象的内存空间。
1.4 创建新的数据类型:类
关键字:class
类中可以设置两种元素:1,字段(域,数据成员) 2,方法(成员函数)
通过 类名.字段名
获取一个对象的成员
image.png
- 如果字段是某个对象的引用,那么必须初始化该引用
- 如果类的某个成员是基本数据类型,即使不进行初始化,java也会确保它具有一个默认值。局部变量不具备这个特性。
1.5 方法,参数和返回值
方法的基本组成部分:名称,参数,返回值,方法体
方法名和参数列表,合称为方法签名
,能唯一 的标识出某个方法
方法的调用 类名.方法名(参数列表)
参数列表
值传递和引用传递,上面说过
void nothing(){
return ;
}
如果返回类型为void,那么 return 关键字只用来退出方法
2.6 构建Java程序
名字可见性
名字空间:反过来使用自己的Internet域名作为工作空间名,以保证类库的独一无二
java1.0和1.1 中 扩展名com,edu,org,net 等都约定为大写,java2开发到一半时,设计者发现这样会引发一些问题,于是,现在整个包名都是小写。
image.png我没能找到到底为什么要小写,网上的主要说法有两种:
1,系统对大小写是否敏感,考虑兼容性。
2,避免混淆对类的识别 com.Student ,看着也啥影像
运用其他构件
当两个类在同一个源文件中时,定义顺序并不影响调用(java中消除了所谓的向前引用问题)
不在同一个源文件中时,可以使用import
关键字导入
import java.util.ArrayList;
import java.util.*;
static 关键字
为某特定域分配单一固定存储空间,不受创建对象多少的影响,甚至根本不需要创建对象,只与类有关联。
static域
或方法
,不会与包含他的那个类的任何对象实例关联,我们称之为类数据和类方法
调用:
1. 对象名.域名(方法名)
2. 类名.域名(方法名)-----首选,强调了static结构,同时为编译器进行优化提供了条件
static 方法不能简单的调用其他非static域或者方法,因为他和当前对象并没有关系。
static域和普通域有较大差别,static域只有一份存储空间,而static方法和普通方法的差距并不大。
1.7 第一个java程序
在所有个类中,都会默认导入java.lang包
类名必须同文件名相同
main(String[] args)
作用:agrs 用来存储命令行参数 ,java在命令行运行的时候要用到
java Test value1 value2
//后面就是两个参数,在main里面args[]就是两个长度的数组value1存在args[1]中,value2存在args[2]中。
//args[0]存储的是命令,其后才是参数!
2.8 注释和嵌入文档
跳一跳
2.9 编码风格
驼峰风格
:
类名首字母大写,多个单词组成紧拼在一起(不要使用下划线),每个单词首字母大写,开头两个首字母如果为单词缩写,不要都戴大写。
WaHaHa
网友评论