网站建设费可分摊几年/成都全网营销推广
文章目录
- 系列文章目录
- 第四章 对象和类
- 4. 1 面向对象程序概述
- 4.2 使用预定义类
- 4.3 用户自定义类
- 4.4 静态字段与静态方法
- 4.5 方法参数
- 4.6 对象构造
- 4.7 包
- 4.8 jar文件
- 4.9 文档注释
系列文章目录
开始写点读书笔记,主要是记录java核心技术卷中自己不太清楚的内容,做出脑图,理清思路。作为笔记,自然不是完全按照书的内容来记录,一方面这本书是经典巨著,肯定不能够表述的像它一样全面通俗易懂,另一方面自己有很多东西理解的也并不透彻,记录只是为了更好的查找和学习,这些blog算是写给自己看的吧。
本章主要围绕第四章对象和类展开。总结的脑图如图所示。
第四章 对象和类
4. 1 面向对象程序概述
面向对象的思想更有助于解决大规模的问题,把大问题划分到小对象,有利于查找错误。
- 封装:决不能让类中的方法直接访问其他类的实例字段。程序只能通过对象的方法与对象数据进行交互。
- 继承:通过扩展一个类来建立另外一个类的过程。
- 多态:
类之间的关系:
- 依赖:use-a,一个类操作或使用另一个类。
- 聚合:has-a,内部有一些其他的类。聚合表示数量不固定,组合表示数量固定。
- 继承:is-a,相当于是该类的一个扩展,所以用is-a。
上面内容需要注意的是:
1、封装:自己以前写程序总是喜欢将类的属性定义为public,因为方便访问数据,对数据进行运算。但是这显然是不对的,本章对类的封装也做出了要求。
2、类之间的关系,用英文表述就很容易理解。
4.2 使用预定义类
对象与变量之间的关系:对象变量并没有实际包含一个对象,它只是一个引用一个对象。
Date deadline; //此时deadline是一个变量
deadline = new Date(); //此时deadline引用了一个类对象。new操作符返回值就是一个变量。
变量的值为null表示该变量目前没有引用任何对象。其中关于null的文章看这个。有一句话我觉得挺好的概括了null:就像每种原始类型都有默认值一样,如int默认值为0,boolean的默认值为false,null是任何引用类型的默认值,不严格的说是所有object类型的默认值。
更改器方法与访问器方法
- 更改器方法:会更改对象,对变量进行修改。
- 访问器方法:只访问对象,不修改对象,不会对原来对象进行修改,可能会产生一个新对象作为返回值。
4.3 用户自定义类
再次强调:使用public标记实例字段是一个很不好的做法,会破坏“封装”特性。
构造器与类同名且没有返回值,构造器总是伴随着new操作符一起调用。
null的使用
-
null表示对象变量没有引用任何变量
-
对null值应用一个方法会产生NullPointException的异常,其中java9提供了两种处理办法。
if(n==null) name="unknown";else name = n;
public Employee(String n,double s, int year, int month, int day){name = Objects.requireNonNullElse(n,"unknown"); }
public Employee(String n,double s, int year, int month, int day){name = Objects.requireNonNull(n,"The name cannot be null"); }
隐式参数和显示参数
- 隐式参数为方法调用的目标或者接收者,即调用的方法改变了类的哪些变量,那些变量称为隐式参数
- 显示参数为方法的参数,需要进行标明。
封装的优点
- 可以改变内部实现。简单来说就是,可以返回特定的值
- 可以判定设定的参数是合理数据,对参数进行错误检查。
- 警告:
- 不要编写返回可变对象引用的访问器方法。
- 如果要返回一个可变对象的应用,首先该对他进行克隆。怎么进行克隆呢?这里要详细讲讲。
基于类的访问权限:
- 一个方法可以访问所属类的所有对象的私有数据。
这个性质也有点迷惑,是不是与反射有关?种个草。
package datePac;public class TestPermission {public static void main(String[] args) {Employee a = new Employee("hhh");Employee b = new Employee("hhm");System.out.println(a.equals(b)); //falsea.GetAMan(b);System.out.println(a.getName()); //hhm}
}class Employee{private String name;public Employee(String name) {this.name = name;}public boolean equals(Employee other) {return name.equals(other.name);}public void GetAMan(Employee others) {this.name = others.name;}public String getName() {return this.name;}
}
final实例字段
-
final实例字段必须在构造对象时就要初始化,并且之后不能修改这个字段的值。
-
final对象修饰可变的类,表示这个引用对象不会再指向其他的地址
其实final与static这两个该怎么区分呢?final表示只能够赋值一次就不会改了,static表示这是类的属性,类名加static的修饰的属性就可以直接调用,虽然这两个经常在一起用于表示常量,但是区分度还是有的。
private final StringBuilder evalustions;
evalustions = new StringBuilder();
public void giveGoldStar(){evaluations.append("str");
}
4.4 静态字段与静态方法
静态变量:
- 属于类,不属于任何单个的对象,静态变量又被称为类变量。静态变量不是不可以被改变。
静态常量:
-
static final
如果省略static那么每实例化一个类,就会创建一个变量的副本 -
公共变量被final修饰之后,自己的值不能被更改了,所以这个可以用来封装返回。
试试上面的这个性质。
静态方法:
- 静态方法可以是认为没有this的方法,静态类不能访问非静态实例字段。
- 可以使用
对象名+"."+静态方法名
来调用静态方法,但一般不这么做 - 两种情况可以使用静态方法:
- 方法不需要访问对象状态
- 方法只需要访问类的静态字段。
工厂方法:
-
不使用构造方法生成类,而是用类名.静态方法产生类
NumberFormat currencyFormat = NumberFormat.getCurrencyInstance(); NumberFormat percentFormat = NumberFormat.getPercentInstance();
-
这么用的原因:
- 无法命名构造器。这里希望用两个无参数的构造器,明显不能够重载。
- 使用构造器无法改变构造对象的类型,工厂方法实际将返回DecimalFormat类的对象,这是一个NumberFormat类的子类。
main方法:
public static void main(String[] args)
- 程序启动时没有任何对象,静态的main方法将被执行并构造程序所需要的对象。
- 每个类都可以有main方法用于测试
4.5 方法参数
程序设计语言中参数调用方法:
- 按值调用:方法接受的是调用者提供的值。
- 按引用调用:方法接受的是调用者提供的变量的地址。
java语言中方法参数:总是按值调用。意思是,传进去的参数总是先构建一个副本,再进行操作。
- 传入基本类型:初始化其值的一个副本,方法结束后,副本释放。
- 传入对象类型:初始化为对象引用的副本,方法结束后,副本释放。但是原来传入的对象类型还是指向原来的对象,相当于通过副本进行修改了原来的对象。但是任然不是按引用类型调用该方法。
java中对方法能做什么和不能做什么?
- 方法不能修改基本数据类型的参数(传入的是值的副本)
- 方法可以改变对象参数的状态(虽然传入的是引用副本,但是原来的对象还是指向了副本更改的对象地址)
- 方法不能让一个对象参数引用一个新的对象(方法内都是对副本进行操作,原来的对象还是会指向原来的地址,你瞎折腾没用)
4.6 对象构造
java提供了多种编写构造器的机制:
1、重载:
- 方法名和参数类型是方法的 签名 ,返回类型不是方法签名的一部分。
- 出现相同的方法名字、不同的参数,便出现了重载。
2、默认字段初始化:
在构造器中没有显示的为字段设置初值,就会被自动的赋值为默认值。
3、无参数的构造器:
- 系统默认提供一个无参数的构造器,将所有实例对象都赋值为默认值
- 如果自己写了构造器,够早对象不提供参数就是不合法的。
4、显示字段初始化
-
可以在类定义中为任何字段赋初值
-
初始值不一定是常量值,可以调用静态方法来获取数值。
package datePac;public class ObjTest {public static void main(String[] args) {Employe a = new Employe("hhm");Employe b = new Employe("hyf");System.out.println(a.reToString());System.out.println(b.reToString());} }class Employe{private String name = "hhh";private static int nextID=0;private int id = assignID();private static int assignID() {int r = nextID;nextID++;return r;}public Employe(String name) {this.name = name;}public String reToString() {return "name:"+name+" id:"+String.valueOf(this.id);} }
4.7 包
包名:采用域名逆序+项目工程名+类名
静态导入:
import static java.lang.System.*
静态导入System类的静态方法和静态字段
在包中增加类:
- 将包的名字放在源文件的开头,即放在定义这个包中各个类的代码前。如果没有包名,就是属于无名包。
package com.mycompany
如果这个源文件不在该位置下,编译不会出错,但是程序没法运行,虚拟机找不到该类。
防止包被其他人修改:
- 禁止加载包以“java."开头,防止修改java自身的包
- 让JAR文件声明包为密封的,防止第三方修改(已过时)
- 使用模块封装包
类路径:
-
系统文件子目录下
-
JAR文件:可以包含多个压缩形式的类文件和子目录(节省空间、改善性能)
- 将类文件放在一个目录中
- 将jar文件放在一个目录中
- 设置类路径(class path),由于总是会搜索java API的类,所以不必显示地包含在类路径中。
- javac总是在当前的目录中查找文件
- java虚拟机仅在类路径中包含“."目录时才会查看当前目录,如果设置了类路径却忘记了”."目录,那么程序能编译却不能运行。
-
虚拟机搜寻类的文件:先查看javaAPI类、再依次查看类路径
-
Windows环境:以分号分割
c:\classdir;.;c:\archive\archive.jar
-
unix环境:用冒号分割
/home/user classdir:.:/home/user/archive/archive.jar
-
-
编译器搜寻类文件:查找包含这个类的包,在类路径所有的位置搜索各个类,再查找包中是否自己定义了这个类,如果找到一个以上的类,就会产生编译错误,
4.8 jar文件
创建jar文件:
jar cvf jarFileName file1 file2...
后面可以接文件夹和图像文件、类文件之类的。
举个例子:jar cvf CalculatorClasses.jar *.class icon.gif
其他的命令参考书中的内容。
清单文件:
-
清单文件被命名为MANIFEST.MF
-
给个jar文件都有一个默认的清单文件,但是逆向更新需要用命令m
jar cfm jarFileName manifestFileName ...
可执行JAR文件:可以使用jar命令中的e选项指定程序的入口点
jar cvfe MuProgram.jar com.mycompany.mypkg.MainAppClass fiels to add
Main-Class: com.mycompany.mypkg.MainAppClass
- 可执行jar文件的执行:
java -jar MyProgram.jar
4.9 文档注释
文档注释看这篇文章吧,写的比较好。还有这篇,看完就差不多了。
继续加油吧,前路遥遥,空调很舒服。