对象和类

面向对象程序设计(简称OOP),面向对象的程序是由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分。

类(class)是构造对象的模板或蓝图。我们可以将类想象成制作小甜饼的切割机,将对象想象为小甜饼。由类构造(construct)对象的过程称为创建类的实例(instance)

​ ---摘至 Java核心技术第10版

封装:将类内部的变量定义为私有,提供公开的访问接口(setter,getter)和功能(方法)

UML符号

image-20200603203148412

方法

方法定义在类的成员位置

一个简单的没有返回值,没有参数的方法,方法必须有返回值没有时要写void

public void fun(){}

有参数和返回值的方法

public String calc(int a,int b){
    return String.valueOf(a+b);
}

静态方法

public static void print(String message){
    System.out.println(message);
}

重写

方法重写是在有类的继承或者对接口的实现的前提,对父类或者父类拥有的可被访问的方法的内部功能进行重新实现,当然也可以选择增强,在方法的内部使用super(代表父类)关键字调用原方法

重写的注意事项:

子类如果和父类在同一个包中,子类可以重写父类的所有非使用private和final的方法(public,default(不写权限修饰符),protected)

子类如果和父类不在同一个包中,子类可以重写父类中使用public和protected修饰的方法

子类的返回值必须大于等于父类的返回值,子类的参数必须小于等于父类的参数

方法的名称和参数必须和父类的相同

重写的方法的访问权限不能小于被重写方法的访问权限

被final修饰的方法不能被重写

构造函数不能重写

被static修饰的方法不能被重写,但可以被重新声明(也就是不能加@Override关键字)

如果被重写的方法没有抛出异常,那么重写方法时无论如何都不能抛出异常,如果被重写的方法抛出了异常,那么重写的方法可以选择不抛出或者抛出的异常类型小与等于被重写方法的异常

// 涉及继承相关的知识,到继承一章补充
// 该关键字可加可不加,加了后如果和父类的方法不同便会提示报错
@Override
public void print(){
    // 使用super关键字调用父类的成员变量和方法(可以在任意位置调用)
    System.out.println(super.name);
    super.print();
    System.out.println("son");
}

重载

重载指在同一个类或者其派生类中,有多个同名的方法,但这些方法参数类型和参数个数,顺序各不相同,跟返回值无关(可以相同也可以不相同),与访问权限修饰符无关,最常见的就是构造函数重载,重载方法可以抛出不同类型的异常

例如

public void fun(){

}

public String fun(String message){
    return message;
}

public void fun(String a,int b){

}

public BigDecimal fun(int a, String b){
    return BigDecimal.valueOf(a).add(new BigDecimal(b));
}

权限修饰符

java中4中权限修饰符分别为public、protect、默认(不写)、private

访问权限 当前类 同包 不同包子类 其他包
public
protected
默认(不写)
private

static静态

被static修饰的变量属于类变量,类共享

被static修饰的方法属于静态方法(类方法),可以直接使用类名调用

静态只可以访问静态成员,不可以访问非静态成员

构造器

构造器和类同名

每个类可以有一个以上的构造器(默认是有一个空参构造的),重载

构造器可以有0个,1个或多个参数

构造器没有返回值

构造器总是伴随着new操作一起调用

请不要在构造器中创建和类的成员变量同名的局部变量

public class Emp {
    private String name;
    public Emp() {
        // 编译错误
        String name = name;
        this.name = name;
    }
}

在一个构造器中可以调用另一个构造器,使用this关键字,调用构造器的代码必须在调用处构造器的第一行(因为怕构造器后面的代码对变量有操作,所以先调用构造进行初始化,因为所有非无参构造的第一行默认调用无参构造,变量的初始化就是由无参构造做的)

public class Emp {
    private String name;

    public Emp() {
        this("sdf");
        this.name = name;
    }

    public Emp(String name) {
        this.name = name;
    }
}

代码块

不仅仅可以在构造函数和创建对象时为变量赋值,还可以在类的位置创建代码块为变量赋值

构造代码块 : 定义在类的成员位置,多个构造代码块根据定义的位置依次执行,每次创建对象时都会调用

静态代码块 : 定义在类的成员位置,使用static关键字修饰,也因其特性,只在类第一次被使用时调用

public class Emp {
    static {
        // 编译错误 静态成员不能访问非静态成员
        //        name = "taoqz";
        age = 18;
        System.out.println("静态代码块");
    }

    {
        name = "taoqz";
        System.out.println("构造代码块");
    }

    {
        name = "zzz";
        System.out.println("构造代码块");
    }

    private String name;
    public static Integer age;
    public Emp() {
        System.out.println("构造方法");
    }

    public Emp(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
Emp emp = new Emp();
System.out.println(emp.getName());

Emp emp1 = new Emp();
System.out.println(emp1.getName());

System.out.println(Emp.age);
// 虽然可以使用对象调用静态成员,但不推荐这么做
System.out.println(emp.age);
静态代码块
构造代码块
构造代码块
构造方法
zzz
构造代码块
构造代码块
构造方法
zzz
18
18

Java允许使用包将类组织和分开管理,命名规则为全部小写,推荐使用公司域名的反写

类的导入

一个类可以使用所属包中的所有类,以及其他包中的公有类(public class)

语法为

// import关键字 全路径类名(包名+类名)
import lombok.Data;

但如果想引入一个包中的多个类就会显得很臃肿和麻烦

// 可以使用*号表示导入该包下的所有类
import java.time.*;

但如果引入的多个包中拥有同名的类,那么需要手动处理,使用全类名创建对象

静态导入

有些工具类提供了很多的静态方法,这些方法都可以使用类直接调用,但如果大量使用该类中的方法,代码也会显得很臃肿,静态导入则解决了该问题

// Math.abs(-1);
// Math.sqrt(2);

// 静态导入后,代码简洁很多
System.out.println(abs(-1));
System.out.println(sqrt(2));

类设计技巧

  1. 一定要保证数据私有,不要破坏其封装性
  2. 要对数据进行初始化,毕竟有着最头疼的问题NullPointerException
  3. 避免类的职责过多,可以选择将其拆分
  4. 优先使用不可变类,保证在多线程环境下数据安全问题
Copyright © TaoQZ 2019 all right reserved,powered by Gitbook作者联系方式:taoqingzhou@gmail.com 修订时间: 2024-11-19 17:25:43

results matching ""

    No results matching ""

    results matching ""

      No results matching ""