面向对象01

129 阅读8分钟

1.1.1对象

对象的三个特性:
1、对象的行为:可以对对象完成哪些操作,或者可以对对象应用哪些方法
2、对象的状态:当调用那些方法时,对象会如何相应
3、对象的标识:如何区分具有相同行为与状态的不同对象

1.1.2类之间的关系

1、依赖(uses-a):例如一个订单类(order)需要使用账户(Account)类,去查看对象的信用状态。像这种一个类的使用或操作需要用到另一个类的对象时,可以说一个类依赖于另一个类。
在实际操作中应该尽可能的使依赖类减少,即尽可能的减少类之间的耦合。
2、聚合:一个类包含另一个类,例如:订单(order)类包含商品(Item)类
依赖与聚合的区别,依赖中的类属于平等关系,而聚合属于整体与部分的关系
3、继承

1.1.3用var声明局部变量

1、如果从变量的初始值可以推导出变量的类型,那么可以使用var关键字声明局部变量
例:   Employee e=new Employee();
可写为 var e=new Employee();
注:var关键字只可用于方法中的局部变量。参数和字段的类型必须声明。

1.1.4使用null引用

和c++一样,在java中使用了为null的对象会触发异常
在java9当中Objects类提供了处理null的便利方法
public Employee(String name, int age) {
    Objects.requireNonNull(name,"The name connot bo null");
    this.name = name;
    this.age = age;
}
运行时会报出Exception in thread "main" java.lang.NullPointerException: The name connot bo null的异常
    该方法的好处:
    1、可以提供这个问题的描述
    2、可以准确指出问题的所在位置

1.1.5显示参数和隐式参数

例如Employee类有如下方法:
public void raiseSalary(double byPercent){
    double raise=salary*byPercent/100;
    salary+=raise;
}
    调用该方法
    number007.raisezSalary(5);
    那么方法raiseSalary方法中就包含两个参数
    1、隐式参数:出现在方法前的Employee对象
    2、括号内的参数值
    

1.1.6封装

private Date hirday;
public Date getHirday() {
    return hirday;
}
```
Date d1=e.getHirday();
double seconds=10*365.3*24*60*1000*60;
d.setTime(d.getTime()-(long)seconds);
```
该代码中d1和d1.hirday引用了同一个对象
在java封装中特别注意如果要返回一个可变对象的引用,首先应该对他进行克隆,产生一个放在另一个新位置上的对象副本。

1.1.7final

class Employee{
    private final String name;
}
final类修饰的对象将不会再改变。
final对于类型为基本类型或者是不可变类的字段尤为有用,但是对于可变的类,可能会引起混乱
例:
private final StringBuilder evaluations;
evaluations=new StringBuilder();
那么该final对象只是表示存储在evaluations变量中的对象引用不会再指向另一个对象,但是该对象的内容可以修改。

1.1.8静态字段与静态方法

1、如果一个字段定义为static,那么每个类就只有一个这样的字段。而对于非静态的实例字段,每个对象都有一个自己的副本。
例:
class Employee03{
    private static int nextid=0;
    private int id;
    public void  setid(){
        id=nextid;
        nextid++;
    }


}
每一个Employee03对象都有一个自己的id字段
而这一个类的所欲实例对象共享一个nextid字段
2、静态常量
例:在Math类中有一个这样的字段
public static final double PI = 3.14159265358979323846;
那么Math类的这一个常量所有对象共享。
3、静态方法
例:Math中的pow方法
public static double pow(double a, double b) {
    return StrictMath.pow(a, b); // default impl. delegates to StrictMath
}
该运算不会使用任何的Math对象,也就是没有隐式参数,不会在对象上执行操作
只有以下两种情况下才可使用静态方法:
1、方法不需要访问对象状态,因为它需要的所有参数都通过显示参数提供
2、方法只需要访问类的静态字段
注意:静态方法不能直接访问普通属性,可以创建对象访问.而普通方法可以直接访问静态属性和普通属性

1.1.9方法参数

java程序设计语言总是采用按值调用的方法即方法得到的是所有参数值的一个副本。
例:有如下一个方法
public static void tripleValue(double x){
    x=x*3;
}
之后调用这个方法
```
double present = 10;
tripleValue(present);
```
执行过程:
1、x初始化为present的一个副本
2、x执行*3操作,但是present不变
3、结束后参数变量x不再使用。
也就是说调用方法前后present的值没有变。
但是方法参数有两种:
1、基本数据类型
2、对象引用
一个方法不能修改基本数据类型的参数,但是当对象引用作为参数时会有所不同。

public static void tripleSalary(Employee e){
    e.raiseSalary(10);
}

    public void raiseSalary(double byPercent){
    double raise=salary*byPercent/100;
    salary+=raise;
    }

var harry=new Employee(...);
tripleSalary(harry)
该方法会将harry对象的相应属性进行修改
执行过程
1、e初始化为harry值的一个副本,(注意在java中harry类似于c++中的指针,harry指向堆中的一个具体的对象,副本e和harry指向同一个对象)
2、调用tripleSalary方法,将e和harry共同指向的对象进行修改,使相应对象的工资提高了10%
3、方法结束x不再使用,但是该方法已经将harry指向的对象进行了修改
但是java对对象采用的并不是引用传递,仍是按值传递,通过一下例子可以看出。
public static void swapEmployee(Employee e1,Employee e2){
    Employee temp=e1;
    e1=e2;
    e2=temp;
}
var x=new Employee(...);
var y=new Employee(...);
swapEmoloyee(x,y);
如果java中对对象采用的是引用传递的话,那么x和y指向的对象应该被改变,然而并没有。
swapEmployee函数现将传入的x,y进行拷贝,之后将拷贝后的副本e1,e2进行交换,但是当程序结束时,e1和e2被丢弃了,原来的x和y指向并没有发生变化。
总结:java中对方法的操作能做什么不能做什么。
1、方法不能修改基本数据类型(数值型或布尔型)的参数
2、方法可以改变对象参数的状态
3、方法不能让对象参数引用一个新的对象

1.2对象构造

1.2.1重载

c++中的重载相同,如果多个方法有相同的名字、不同的参数便出现了重载。java中要想完整的描述一个方法,需要指定方法名以及参数类型。这个叫做方法的签名
注意:返回值类型不是方法签名的一部分,也就是不能有两个名字相同、参数相同但是返回值类型不同的方法。
因为编译器在编译时必须挑选出具体调用哪个方法,它依靠函数命和参数进行识别,只有进入方法,才会涉及返回值,如果两个方法名称、参数均相同,编译器就不知道要执行哪个方法,也就谈不上返回值了。

1.2.2默认字段初始化

1、构造器中如果没有显示的为某些字段赋值,那么会被默认的赋为默认值:数值:0  布尔:false  对象引用:null

1.2.3无参数构造器

很多类都包含一个无参构造器,有无参构造器创建对象时,对象的状态会被设置为适当的默认值
如果写一个类时没有编写构造器,那么就会提供一个无参构造器,该构造器会将所有的实例字段设置为默认值。
但是如果一个类中提供了至少一个构造器,但是没有无参构造器,构造对象时就不可用无参构造。

1.2.4调用另一个构造器

关键字this只是一个方法的隐式参数,不过当构造器中的第一个语句为形如this(...)(注意只能是第一个语句),那么构造器将调用同一个类的另一个构造器。
例:
public People(int a){
    this("People #"+nextid,a);
    nextid++;
}
private People(String s,int i){
    name=s;
    age=i;
}

People a=new People(10);
People b=new People(20);
此时调用参数为int a的构造器,由于在该构造其中第一句为this()将会调用第二个构造函数。

1.2.5初始化块

java中还有第三种机制,名为初始化块当构造这个类的对象时,先会执行初始化块,之后才会执行构造器
例:

{
    id=nextid;
    nextid++;
}
若在代码块前面加上static,那么就变成了静态代码块,静态代码块在该类第一次加载的时候就会被调用(静态代码块仅仅被调用这一次)

1.2.6访问权限

java中访问修饰符主要有三类:private public 默认
区别:
public                      任意类均可使用
private                     只能由定义他们的类使用
默认(为指定publicprivate)  可以被同一个包中的所有方法访问