1. 软件的生命周期
产品提出需求
分析以及规划
软件编码及其调试(自测,联调)
上测试环境,给测试人员测试(提bug)
上 linux 生产服务器(运维人员维护,修改bug,系统的升级迭代)
被弃用
2. 软件设计原则
可重用性(减少重复的代码)
可拓展性
可维护性
高内聚、低耦合(模块之间要相互独立)
面向过程:(Procedure Oriented Programming)pop是流程性的执行,需要去处理方法与方法之间的关系,或者是方法的调用
存在问题:从上往下设计的方式,分别考虑每个方法干啥,细分很难。
需求:做饭(买菜,做饭,做菜,吃饭,洗碗)
1. 面向对象:(Object Oriented Programming )OOP ,站在对象的角度去考虑问题(处理类和类之间的调用和操作,把每一个类,拆分成不同的功能)
2. 面向对象三大特征:
封装:(可以把功能的特征的一些事物封装成一个对象,可以将细节隐藏起来,通过公共方法来调用,暴露功能)
继承:做到代码的复用
多态:把子类赋值给父类对象,调用的时候,还是去调用子类,表现出不同的特征
3. 类:具有相同特征和行为的事物进行一个抽象。
电脑:cpu、内存、电源、主板
人:名字,身高,体重
4. 对象:是类的实例,类是对象的模板。
5. 面向对象和面向过程的区别:
面向过程会更平面化
面向对象会更加立体
你中有我,我中有你
我们程序设计追求“高内聚,低耦合”
高内聚:类的内部数据操作细节自己完成,不允许外部干涉
低耦合:仅对外暴露少量的方法用于使用。
隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露岀来。这就是封装性的设计思想。
把对象的状态和行为看成了一个统一的整体,放到一个独立的模块中(类)
做到信息隐藏,把不需要外界看到的信息隐藏起来(private进行私有化),向外提供方法,保证外界的安全访问。
提供了代码的复用性(可以减少重复代码)
使用者可以正确操作,方便使用系统功能
把实现细节隐藏起来,提供了安全性
通过对不同的方法属性设置不同的权限修饰符来达到对类进行封装的目的。
权限从小到大顺序为:private < 缺省 < protected < public
具体的修饰范围:
修饰符 | 类内部 | 同一个包 | 不同包的子类 | 同一个工程 |
private | Yes | |||
(缺省) | Yes | Yes | ||
protected | Yes | Yes | Yes | |
public | Yes | Yes | Yes | Yes |
权限修饰符可用来修饰的结构说明:
5.1 规范
set 后面的单词采用驼峰命名法,并且使用原单词 setAge(...)
get getAge();
private int age;
public void setAge(int a){
age = a;
}
public int getAge(){
return age;
}
变量:就近原则
this 关键字:代表当前对象的引用
需求:建一个学生类,name ,age,address 提供set get 方法。
public class Student {
private String name;
private int age;
private String address;
public Student(){
}
public Student(String name){
this.name = name;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
public void setAddress(String address){
System.out.println(this);
this.address = address;
}
public String getAddress(){
return address;
}
}
5.2 对于私有属性传参
使用 set get
使用构造器
5.3 注意:
static 静态的不能使用this 关键字,默认get 如果你不写 this,底层也会给我们加上 this
this 关键字也可以再构造器里面使用
定义:基于某个父类对其进行拓展,定义新的子类,子类可以继承父类原来的属性和行为,并且可以增加父类没有的特性,或者覆盖父类中的某些特性
继承关系:is a 用是造句
继承的基础语法:
使用 extends 关键字
public class 子类类名 extends 父类类名{
写自己的特征
}
注意:
java 只支持单继承,允许多重继承(一个类只能有一个直接父类,但是可以有多个间接父类)
任何类都是 Object 的子类
创建对象时,构造方法如何执行
先执行父类构造器(先执行父类静态代码块,再执行子类静态代码块)
子类构造器
set get 方法
创建对象时,创建的是谁,打印 this 对象就是谁(多态)
3.1 重写:当父类特征不能满足子类特征的时候,可以对父类的方法进行重写
3.2 要求:
3.3 重写和重载的区别
子类的访问修饰符 >= 父类本身
父类不能使用 private 修饰
方法返回类型,子类 <= 父类
没有任何关系,只不过因为名字看起来相同,所以就拿来对比
重载:发生在同一个类中,方法名相同,参数列表不同,和方法的返回类型无关
重写:override
重载:overload
5.1 java.lang.Object类的理解
是Java中所有类的父类,类似于二叉树中的根节点,定义了一些通用的方法。
方法名 | 类型 | 描述 |
public Object() | 构造方法 | 构造器 |
public boolean equals( Object obj) | 普通方法 | 对象比较 |
public int hashCode() | 普通方法 | 获取Hash码 |
public String toString() | 普通方法 | 对象打印时调用 |
5.2. java.lang.Object类的说明:
Object类是所Java类的根父类
如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类
Object类中的功能(属性、方法)就具通用性。
属性:无
方法:equals() / toString() / getClass() /hashCode() / clone() / finalize()
wait() 、 notify()、notifyAll()
5.3. equals()方法
public boolean equals(Object obj) {
return (this == obj);
}
使用说明:
手动重写举例:
class User{
String name;
int age;
//重写其equals()方法
public boolean equals(Object obj){
if(obj == this){//判断形参和比较对象的引用地址是否相同,相同直接返回true
return true;
}
if(obj instanceof User){
User u = (User)obj;
return this.age == u.age && this.name.equals(u.name);
}
return false;
}
}
自动生成的,自动生成快捷键ctrl+alt+S,选择自动生成hashCode和equals方法
自动生成的代码:
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
回顾 == 运算符的使用:
== :运算符
可以使用在基本数据类型变量和引用数据类型变量中
如果比较的是基本数据类型变量:
比较两个变量保存的数据是否相等。(不一定类型要相同)
如果比较的是引用数据类型变量:
比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体
使用说明
5.4. toString()方法
toString()的使用:
当我们输出一个对象的引用时,实际上就是调用当前对象的toString()方法
Object类中toString()的定义:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
像String、Date、File、包装类等都重写了Object类中的toString()方法。使得在调用对象的toString()时,返回"实体内容"信息。
自定义类也可以重写toString()方法,当调用此方法时,返回对象的"实体内容"
重写toString()
//自动实现
@Override
public String toString() {
return "Customer [name=" + name + ", age=" + age + "]";
}
1. 从结果上看:继承性
子类继承父类以后,就获取了父类中声明的属性或方法。 创建子类的对象,在堆空间中,就会加载所父类中声明的属性。
2. 从过程上看:
当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类的构造器,进而调用父类的父类的构造器,...直到调用了java.lang.Object类中空参的构造器为止。正因为加载过所的父类的结构,所以才可以看到内存中父类中的结构,子类对象才可以考虑进行调用。
3. 强调说明:
虽然创建子类对象时,调用了父类的构造器,但是自始至终就创建过一个对象,即为new的子类对象。
可以理解为一个事物的多种形态。比如数据库的连接方式,我们定义好了数据库的连接,也规定了连接时的步骤,但是我们并不知道用户会采用什么数据库,在没有多态以前我们只能针对不同的数据库写不同的连接方法,而有了多态以后我们只需要定义好数据库的类并书写好连接方法,让所有的数据库继承数据库类并重写数据库连接方法。
这样我们在调用的时候只需要通过声明数据库类并指向数据库的子类的方式,**(即数据库类的引用指向继承了数据库类的具体实现类的对象)**就可以进行数据库连接。而不是需要针对不同的数据库书写不同的连接方式。
对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
编译时和运行时类型不一致,产生了多态
代码举例:
Person p = new Man();
Object obj = new Date();
3.1多态性的使用前提:
① 类的继承关系 ② 方法的重写
3.2多态性的应用举例:
举例一:
public void func(Animal animal){//Animal animal = new Dog();
animal.eat();
animal.shout();
}
举例二:
public void method(Object obj){
}
举例三:
class Driver{
public void doData(Connection conn){//conn = new MySQlConnection(); / conn = new OracleConnection();
//规范的步骤去操作数据
// conn.method1();
// conn.method2();
// conn.method3();
}
}
3.3 多态性使用的注意点:
对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)
个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就==不能==再访问子类中添加的属性和方法
3.4 多态使用总结
多态的作用:提高了代码的通用性,常称作接口重用
使用前提:①需要存在继承或者实现关系 ②有方法的重写
成员方法:
成员变量:不具备多态性,只看引用变量所声明的类
向上转型:多态
4.1 为什么使用向下转型:
有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。如何才能调用子类特的属性和方法?使用向下转型。
4.2 如何实现向下转型:
使用强制类型转换符:()
Person p = new Man();
Man m1=(Man)p2;//向下转型
4.3 使用时的注意点:
① 使用强转时,可能出现ClassCastException的异常。
② 为了避免在向下转型时出现ClassCastException的异常,我们在向下转型之前,先进行instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。
③ 只有对象A是B的子类实例化对象或者在下层的子类,才能向下转型
4.4 instanceof的使用:
① a instanceof A:==判断对象a==是否是==类A的实例==。如果是,返回true;如果不是,返回false。
② 如果 a instanceof A返回true,则 a instanceof B也返回true.其中,类B是类A的父类。
③ 要求a所属的类与类A必须是子类和父类的关系,否则编译错误。
p instanceif Man//左边是变量名,右边是类的类型
1.谈谈你对多态性的理解?
**2.多态是编译时行为还是运行时行为?**运行时行为
class Base {
int count = 10;
public void display() {
System.out.println(this.count);
}
}
class Sub extends Base {
int count = 20;
public void display() {
System.out.println(this.count);
}
}
public class FieldMethodTest {
public static void main(String[] args) {
Sub s = new Sub();
System.out.println(s.count);//20
s.display();//20
Base b = s;//多态性
//==:对于引用数据类型来讲,比较的是两个引用数据类型变量的地址值是否相同
System.out.println(b == s);//true
System.out.println(b.count);//10
b.display();//20
}
}