对象
对象的三个主要特性
- 对象行为(即对象的方法,调用后会相应的改变对象的状态)
- 对象状态(对象中保存着的描述当前特征的信息)
- 对象标识(可以理解为同一个类实例化出来的不同对象,他们之间状态是独立的)
什么是面向对象?
面向对象程序设计(OOP)是当今主流的程序设计泛型
- 面向过程与面向对象
规模较小:面向过程方式比较理想
规模较大:面向对象方式比较理想
面向对象重要特性
封装继承多态
- 封装
将数据合行为组合在一个包中,并对对象是的使用者隐藏了数据的实现方式- 概念
- 实例:类生成的对象
- 实例域:指对象中的数据
- 方法:指操纵数据的过程
- 实现封装的关键:绝对不能让类中的方法,直接的访问其他类的实例域,程序仅通过对象提供的的方法与对象数据进行交互,相当于赋予了对象“黑盒”的特征,这是提高重用性和可靠性的关键(即内部无论如何变化,只要仍旧提供同样的方法操作数据,其他对象就不会影响到功能)(封装性良好表明其他类无法改变该对象状态,仅该对象的类的操作方法可以)
- 概念
- 继承
类
概念
类是构造对象的模板或者蓝图,由类构造对象的过程称为创建类的实例
类之间的关系
- 依赖(uses-a)
最明显常见的关系,如果一个类的方法操纵另一个类的对象,我们就说一个类依赖于另一个类
ps:应该尽可能的减少类的互相依赖(如果A不依赖于B,那么B的改变不会使A出现bug),即耦合度最小 - 聚合(has-a)
类A对象包含类B对象 - 继承(is-a)
类A不但包含从类B继承的方法,还会拥有一些额外功能
UML(统一建模语言)
用于绘制类图,描述类之间的关系(用不同的箭头表示)
编写一个类
- 构造器:用于构造并初始化新的实例
- 特点:
- 名字与类名相同
- 每个类可以有一个以上构造器
- 构造器没有返回值
- 需要伴随着new操作进行调用
- 使用:用过new关键字进行
ps:一个对象变量并没有实际包含一个对象,而是仅仅引用一个对象(存的是对象地址)(任何对象都是存储地址或null)
- 特点:
- 更改器方法和访问器方法
会对对象进行改动的方法叫做更改器方法,只访问对象而不修改对象的方法叫做访问器方法- 访问器方法:典型的getName()方法内部直接return name;
- 好处:方法设定了一个只读域,一旦构造器设置完毕,就没有任何办法进行修改,确保不会把数据破坏
- 建议:一个良好的数据访问或者修改的方式应该是:(两个好处:1.可以改变内部实现,按照需要实现数据处理返回内容。2.可以在方法内部方便的做错误检查)
- 一个私有的数据域
- 一个共有的域访问器方法
- 一个共有的域更改器方法
- 访问器方法:典型的getName()方法内部直接return name;
- 建议:将实例域标记为private,防止其他代码利用这种存取权限进行修改
- 方法的显式参数和隐式参数:出现在括号内的参数是显式,没出现在括号内为隐式(例如内部操作了对象,用了this)
ps:方法体中用this.xxx
可以更好地将实例域与局部变量区分开来 - final实例域
加入了final关键字以后,表示构建对象时必须初始化这样的域,并且不能再对其进行修改
ps:final关键字知识表示存储在变量中的对象不会再指向其他对象,不过这个对象可以更改(即引用的地址不会再改变,但是地址指向内容如何更改都可以) - static静态域
加入了static标签以后,改属性就表示为该类所有对象所共有的一个属性了,它是在类被实例化前就存在在内存中的,仅仅属于类,而不属于任何对象。 - static静态方法
- 使用静态方法的情况:
- 不需要访问对象状态,所需参数都是通过显式提供的
- 一个方法只需要访问类的静态域
- 工厂方法构造对象
- 优势:解决了无法命名构造器的问题(此方法可以通过任何命名来构造对象),解决了使用构造器时无法改变所构造的对象类型的问题
- 使用静态方法的情况:
ps:调用静态方法时,建议使用类名.方法名()
,而不是具体对象名,因为这样容易混淆以为是对对象进行操作,其实是对类进行操作
方法参数的值传递和引用传递问题
按值传递:传递的是参数的值
按引用传递:传递的是参数的引用地址
一个方法可以修改传递引用所对应的变量值,而不能修改传递值所对应的变量内容
方法参数传递可以分为两种类型:
1.基本数据类型(数字,布尔值)
2.对象引用
Java内部其实总是采用按值传递:也就是说方法得到的是所有参数值的一个拷贝,而不能修改传递给它的变量的内容
只不过如果是基本数据类型则是直接存储的对应的值拷贝,而如果是对象则存储的是内存地址,所以若是传递对象作为参数,传递的其实是内存地址的拷贝,进行的改变是会改变该对象的状态的
可以写一个两个对象swap交换的函数进行测试,实际上是不会交换成功数据的,因为底层是内存地址的值传递(核一P120)*
编写不同的构造器
- 重载(如果有多个方法,具有相同的名字,不同的参数,就构成了重载)
方法的签名(包含方法名和传入参数的类型,注意返回类型不构成签名)
ps:构造时最好给声明的变量赋予初值,提升程序代码的可读性 - 无参构造器:默认情况下有无参构造器,一旦自己书写了构造器,要记得自己手动写上无参构造器,否则会报错
- this的用法
- 1.表示生成实例对象的隐式参数例如(this.salary)表示该实例化对象域中的salary属性
- 2.在构造其器中第一个语句用
this(xxx,xxx)
表示,调用该类的另一个构造器,这对于减少相同代码书写有一定帮助
类
包
使用包的主要原因是确保类名的唯一性
通常可以使用因特网域名的逆序写法作为包名
- 类的导入(import)
可以使用通配符进行导入
ps:当两个包存在相同的类名类时,不能用xxx.*导入
如果要两个相同类名的类同时使用,则新建时在每个类的类名前面加上完整的类路径例如(java.util.Date deadline = new java.util.Date()
) - 静态导入
静态导入后可以直接使用类内的静态方法和静态域,而不必加类名前缀
例如:import static java.lang.System
---->out.println("Good!")
- 将类放入包中
- 1.在类的首行写上
package com.horstmann.corejava;
- 2.将包中文件放到与完整包名匹配的子目录中
ps:即使类源文件不在对应包名目录下也可以编译,但是运行会报错,除非放在正确位置上
- 1.在类的首行写上
- 规范的类放置方法
- 1.把类按照包结构放到目录中
- 2.把JAR文件放到目录中
- 3.设置类路径