从第一章到第二章整整隔了一个月的时间,这速度也是慢的无语了。因为这个月负责开发公司一个SaaS类型APP,忙的昏天暗地终于上线了,这才有时间写个博客。本章还是以概念为主,有点枯燥重在理解。
第一节:对象
名词解释
- OOA-Object Oriented Analysis-面向对象分析
- OOD-Object Oriented Design-面向对象设计
- OOP-Object Oriented Programming-面向对象程序设计
面向对象基本特性
- 万物皆可为对象:任何一件事物都可以表示为程序中的对象
- 程序是对象的集合:它们通过发送信息来告知彼此所需要做的
- 每个对象都有自己的或有其他对象所构成的存储:如:对象中引用其他对象
- 每个对象都拥有其类型:每个对象都是某个类class的实例,这里的类就是指类型
- 某一指定类型的所有对象都可以接受相同的信息:如:person对象拥有father和mother对象的所有性质
- 一句话总结就是:对象具有状态行为和标识,内部数据即状态-方法即行为-存在内存中的唯一地址即标识
面向对象三个特性
- 封装(encapsulate):把客观事物封装成抽象的类,并且类中的属性和方法有自己指定的访问权限。隐藏具体细节,是调用者只能遵循自己定义的规则,方便权限控制
- private:成员变量和方法只能在类内被访问,具有类可见性
default:成员变量和方法只能被同一个包里的类访问,具有包可见性
protected:可以被同一个包中的类访问,被同一个项目中不同包中的子类访问
public:可以被同一个项目中所有类访问,具有项目可见性,这是最大的访问权限
- 继承:指子类有父类所有的功能,并可以重写或补充自己的方法
关键字:extends ,Java是单继承关系所有对象的父类都是Object,多继承容易使代码混乱,单继承使只有一个父类代码逻辑更清晰如:它们都是相同的数据类型都有相同的方法功能且单继承结构对垃圾回收机制实现变得容易的多。Java是单继承多实现接口的结构。
重载(overloading):同一个类中有相同的方法名字不同的参数叫做方法重载
重写(overriding):两个类之间必须存在继承关系,且子类重写了父类中有的方法,包括方法名字参数返回值都相同,如果需要调用父类中方法须用super关键字调用
- 多态:指一个实现类在不同的情景下有不同的实现方式,即不同的类可以实现相同的接口来完成不同的任务,但我们可以通过相同的方式予以调用
条件:必须存在继承关系,子类重写父类的方法,向下转型
- 转化规则:子类转换父类向上转型可直接赋值,父类转换子类向下转型许强制类型转换且无法调用子类特有方法
package com.fengzb.java002.object; /** * @Description 封装 * @Author jxb * @Date 2017-06-10 22:52:20 */ public class Person { /** * 手 */ private String hand; /** * 脚 */ private String foot; /** * 头 */ private String head; public String getHand() { return hand; } public void setHand(String hand) { this.hand = hand; } public String getFoot() { return foot; } public void setFoot(String foot) { this.foot = foot; } public String getHead() { return head; } public void setHead(String head) { this.head = head; } /** * 无参构造方法 */ public Person(){ System.out.println("--jxb--Person--Person:我是Person无参构造方法"); } /** * @Description private方法可以在同一个类中调用 * @Param * @Author jxb * @Date 2017-06-11 23:19:48 */ private void isPerson() { System.out.println("--jxb--Person--isPerson:" + "我是人"); } /** * @Description 默认方法只有同一个包里可用 * @Param * @Author jxb * @Date 2017-06-12 12:32:00 */ void useHeadThinking() { System.out.println("--jxb--Person--useHeadThinking:" + "人用头想事情"); } /** * @Description protected方法同一个包可见,同一个项目不同包的子类可见 * @Param * @Author jxb * @Date 2017-06-12 12:36:06 */ protected void useFootWalk() { System.out.println("--jxb--Person--useFootWalk:" + "人用脚走路!"); } /** * @Description public方法可以同项目中所有类访问 * @Param * @Author jxb * @Date 2017-06-11 23:17:15 */ public void useHandEat() { System.out.println("--jxb--Person--useHandEat:" + "人用手吃饭!"); } /** * @Description private方法可以在同一个类中调用 * @Param * @Author jxb * @Date 2017-06-11 23:19:48 */ public void personDetail() { System.out.println("--jxb--Person--personDetail:" + "我是人类"); } }
Person
package com.fengzb.java002.object; /** * @Description 继承 * @Author jxb * @Date 2017-06-12 12:25:53 */ public class Mother extends Person { /** * 姓名 */ private String name; /** * 年龄 */ private int age; /** * 性别 */ private String sex; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } /** * @Description * @Param * @Author jxb * @Date 2017-06-11 23:17:15 */ public void useHandEat() { System.out.println("--jxb--Person--useHandEat:" + "wbb用手吃饭!"); } /** * @Description * @Param * @Author jxb * @Date 2017-06-11 23:17:15 */ public void motherDetail() { System.out.println("--jxb--Father--motherDetail:" + this.name + "-" + this.getAge() + "-" + this.getAge()); } }
Mother
对象的生命周期
- 对象在堆(heap)的内存池中动态的创建,这种方式只有运行时才能知道有多少对象需要被创建,他们的生命周期如何,以及它们的具体类型。
- Java用NEW关键字来创建对象,Java提供垃圾回收的机制,它可以自动发现对象何时不再使用并继而销毁它。
异常处理
- 异常也是一种对象,它往往处于编程语言中,与程序正常执行路径并行,在发生错误时执行另一条路径。因为是完全另一条路径执行,所以不会干扰正常代码的运行
- Java从一开始就内置了异常处理,它要求你必须使用它,如果没有编写正确的异常处理代码,在编译时就会报错,这也是Java健壮性和安全性的表现
并发编程
- 我们想把问题分割成多个可独立运行的任务,在程序中这些独立运行的部分叫做线程,这就是并发
- 当多个线程访问同一个资源的时候有可能会有问题,我们必须使某个线程锁定某个资源,完成其任务后释放资源,这是线程锁也叫同步线程
对象存储位置
- 寄存器:这是最快的储存区,位于处理器内部,我们无法用程序操控它也无法感知它的存在
- 堆栈:位于RAM(随机访问储存器)中,堆栈指针下移分配内存上移释放内存,速度仅次于寄存区,Java系统必须知道所有项的生命周期以便用上下移动堆栈指针,虽然某些数据(对象引用)存储其中,但对象本身并不在其中
- 堆:一种通用的内存池也存在RAM中,用于存放所有Java对象。不需要知道对象的生命周期,需要的时候直接NEW出一个对象堆堆自动分配空间,但当清理的时候却要花费点时间
- 常量储存:常量因为是不会被改变的所以通常放在程序中,也可以放在ROM(只读存储器)中
- 非RAM存储:一些对象完全存活于数据之外比如:流对象和持久化对象。这种对象通常存储在硬盘上
- 特例基本类型:创建一个并非是引用的自动变量,直接存储在栈中,因此更加高效
- 用引用操作对象:就像遥控器操纵电视机一样,没有电视机遥控器还可以存在只是不能发出任何消息,所以为了安全起见创建一个引用的时候就初始化一个对象
第二节:类
-
作用域
- 作用域决定了其内部变量的可见性和生命周期,用花括号表示。但用new创建的引用对象,它可以存活于作用域之外,虽然引用对象不能用了,但是new出来的对象还一直在内存中,Java通过垃圾回收机制最终回收无用的对象,finalize方法在垃圾回收之前调用,但不推荐使用
-
类
- 用class关键字后面紧跟着新的类型名称,用来抽象某一类的对象。命名方式:首字母大写每个单词的首字母大写
- 依赖(uses-a)(dependence)
聚合(has-a)(aggregation)
继承(is-a)(inheritance)
设计类时尽量做到高内聚低耦合
所有的标识符都应该以字母(A-Z或者a-z),美元符($)、或者下划线(_)开始
- 用class关键字后面紧跟着新的类型名称,用来抽象某一类的对象。命名方式:首字母大写每个单词的首字母大写
-
属性
- 属性就是对象本身的一些描述字段,他可以是基本数据类型也可以是其他对象的引用。命名方式:首字母小写每个单词的首字母大写
-
方法-参数-返回值
- 方法是对象行为的描述,可以有很多方法,利用传递的参数做业务处理返回想要得到的值。命名方式:首字母小写每个单词的首字母大写
构造器:与类名相同,每个类可以有一个以上的构造器,没有返回值,伴随new关键字被调用。一个类中如果没有构造器,系统就会默认一个无参的构造器,数值型为0,布尔型为false,对象为null
- 方法是对象行为的描述,可以有很多方法,利用传递的参数做业务处理返回想要得到的值。命名方式:首字母小写每个单词的首字母大写
-
static
- static类是不被允许的,通常使用内部类实现静态类
- static方法在类被加载后jvm就可以在运行时数据区读取到,因此不依赖创建对象就可以直接调用类名.方法名()。可以调用其他static方法,只能调用static数据,不能用super和this调用
- static变量在jvm加载的时候只会分配一块内存(节省内存),可以用类名.变量名来调用,private static表示私有的静态数据。而实例变量会每new一个对象就是一块内存
- static代码块通常叫做静态代码块,在类加载的时候被顺序执行,在构造方法之前执行
-
final
- final类不能被继承,里面的方法都是final的,没有继承所以就没有重写
- final方法不允许被覆盖,为了锁定其方法不被扩展或者为了提高效率。private方法无法继承因此private方法默认是final的(有争议)
- final变量一但被赋值就无法改变
- final参数可以运用但不能被改变
- final+static表示不能被改变的静态数据或方法也叫全局常量
-
初始化数据
- 在声明中赋值
- 在初始化块中赋值
- 在构造方法中赋值
- 声明>初始化块>构造方法
- Father
package com.fengzb.java002.object; /** * @Description 测试类 * @Author jxb * @Date 2017-06-11 23:07:24 */ public class ObjectTest { public static void main(String[] args) { System.out.println("--jxb--ObjectTest--main:----------测试继承----------begin"); /** * private 方法无法调用 */ Person person = new Person(); person.useHandEat(); /** * 向上转型 拥有父类的可见方法,当子类重写父类方法时,调用的是子类的方法-多态 */ Person pMother=new Mother(); pMother.useHandEat(); /** * 编译和运行均不会报错 * 向下转型需要强制类型转换 */ Mother ppMother = (Mother)pMother; ppMother.setName("枫"); ppMother.motherDetail(); /** * 编译不会报错但运行会报java.lang.ClassCastException(类型转换异常) * 可以用instanceof 来判断是否可以向下转型 */ Person mperson = new Person(); //这里转换后运行会出现异常 //Mother mother = (Mother) mperson; //mother.useHandEat(); if(mperson instanceof Mother){ Mother mother = (Mother) mperson; mother.useHandEat(); System.out.println("--jxb--ObjectTest--main:很显然走不到这里"); } System.out.println("--jxb--ObjectTest--main:----------测试继承----------end"); System.out.println("--jxb--ObjectTest--main:----------测试final static----------begin"); /** * address输出的是:北京昌平,所以具体加载顺序如下: * 1:声明式赋值被加载 * 2:静态模块被加载且只加载一遍(这个实际还是很有用的) * 3:父类构造方法被加载 * 4:本身构造方法被加载 */ Father father = new Father(); Father father1 = new Father(); System.out.println("--jxb--ObjectTest--main:"+Father.address); /** * final无法赋值 */ //Father.TEL="18588888888"; System.out.println("--jxb--ObjectTest--main:"+Father.TEL); System.out.println("--jxb--ObjectTest--main:----------测试final static----------end"); } }
ObjectTest
包(package):将类组织起来,一般用域名的逆序作为包名。如果一个类里面引用相同名字的外部类,可以通过inport关键字导入包路径来区分
注释:单行(//)以及多行注释(/* */),注释内容Java虚拟机会自动过滤
注释文档:JavaDoc可以生成html文档,以@符号为标识符如:@version