本章内容

1.类与实例
2.方法
3.构造方法★★
4.方法重载Overload
5.对象
6.抽象类
7.接口
8.package包

1.类与实例

现实世界中,我们定义了“人”这种抽象概念,而具体的人则是“小明”、“小红”、“小军”等一个个具体的人。所以,“人”可以定义为一个类(class),而具体的人则是实例(instance)

类必须先定义才能使用。类是创建对象的模板,创建对象也叫类的实例化。instance是对象实例,instance是根据class创建的实例,可以创建多个instance,每个instance类型相同,但各自属性可能不相同,完整语法为:

1
2
3
4
5
6
7
8
9
10
11
12
[public][abstract|final]class<class_name>[extends<class_name>][implements<interface_name>] {
// 定义属性部分
<property_type><property1>;
<property_type><property2>;
<property_type><property3>;

// 定义方法部分
function1();
function2();
function3();

}

提示:上述语法中,中括号“[]”中的部分表示可以省略,竖线“|”表示“或关系”,例如 abstract|final,说明可以使用abstract或final关键字,但是两个关键字不能同时出现

对实例的说明:

  • public:表示“共有”的意思。如果使用public修饰,则可以被其他类和程序访问。每个Java程序的主类都必须是public类,作为公共工具供其他类和程序使用的类应定义为public类
  • abstract:如果类被abstract修饰,则该类为抽象类,抽象类不能被实例化,但抽象类中可以有抽象方法(使用abstract修饰的方法)和具体方法(没有使用abstract修饰的方法)。继承该抽象类的所有子类都必须实现该抽象类中的所有抽象方法(除非子类也是抽象类)
  • final:如果类被final修饰,则不允许被继承
  • class:声明类的关键字
  • class_name:类的名称
  • extends:表示继承其他类
  • implements:表示实现某些接口
  • property_type:表示成员变量的类型
  • property:表示成员变量名称
  • function():表示成员方法名称

2.方法

方法method是一段用来完成特定功能的代码块,类似于其它语言中的函数function。方法用于定义该类或该类的实例的行为特征和功能实现。

1
2
3
4
5
public class Test {
[public|private|protected][static]<void|return_type><method_name>([paramList]) {
// 方法体
}
}

方法返回值通过return语句实现,如果没有返回值,返回类型设置为void,可以省略return。return作用:1. 返回值 2.结束程序运行

各修饰符含义如下:

  • public、private、protected:表示成员方法的访问权限
  • static:表示限定该成员方法为静态方法
  • final:表示限定该成员方法不能被重写或重载
  • abstract:表示限定该成员方法为抽象方法。抽象方法不提供具体的实现,并且所属类型必须为抽象类

方法的参数有实参和形参之分,我们现在深入思考一下,方法中可以传递什么类型的值

  • 基本数据类型:整型,字符型,浮点型,布尔型

    1
    public static void test(int a, char b, double c, float d, boolean e){}
  • 引用数据类型:字符串,接口

    1
    public static void test(String a){}
  • 数组类型传递:

    1
    public static void test(int[] a, char[] b, double[] c,...){}
  • class类类型传递:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public static void test(employee a,employee b){}
    ...
    class employee{
    private int id;

    public int getId() {
    return id;
    }
    public void setId(int id) {
    this.id = id;
    }
    }

总结:
基本数据类型、引用类型在内存中的存储方式:

  • 基本数据类型:存放在栈内存中。用完就消失
  • 引用类型:在栈内存中存放引用堆内存的地址,在堆内存中存储类、对象、数组等。当没用引用指向堆内存中的类、对象、数组时,由 GC回收机制不定期自动清理

3.构造方法

构造方法是专门用来创建对象的方法,通过关键字new来创建对象,就是在调用构造方法
格式:public 类名称(参数类型 变量名称){方法体}

注意事项:

  • 构造方法的名称必须和所在的类名称完全一样,就连大小写也一样
  • 构造方法不要写返回值类型,连void都不要写
  • 构造方法不能return一个具体的返回值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class OOP {
public static void main(String[] args) {
// 在通过new操作符调用的时候,构造方法的参数数量、位置和类型一一对应
Person p = new Person("chd",18,10086);
System.out.println(p.getAge());
// 调用实例对象的属性
System.out.println(p.tel);
System.out.println(p.getAge());
System.out.println(p.getName());
}
}

class Person {
// 这个不能省略,用以声明变量
private String name;
private int age;
public int tel;

// 这就是Java的构造方法,类似于python的def __init__函数
public Person(String name, int age,int tel) {
this.name = name;
this.age = age;
this.tel = tel;
}

public String getName() {
return this.name;
}

public int getAge() {
return this.age;
}
}

多构造方法

可以定义多个构造方法,在通过new操作符调用的时候,编译器通过构造方法的参数数量、位置和类型自动区分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Person {
private String name;
private int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}

public Person(String name) {
this.name = name;
this.age = 12;
}

public Person() {
}
}

如果调用new Person("Xiao Ming", 20);,会自动匹配到构造方法public Person(String, int)

如果调用new Person("Xiao Ming");,会自动匹配到构造方法public Person(String)

如果调用new Person();,会自动匹配到构造方法public Person()

4.Overload方法重载

这种方法名相同,但各自的参数不同(即参数数目不同,参数数据类型不同),称为方法重载(Overload)。注意:方法重载的返回值类型通常都是相同的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Hello {
public void hello() {
System.out.println("Hello, world!");
}

public void hello(String name) {
System.out.println("Hello, " + name + "!");
}

public void hello(String name, int age) {
if (age < 18) {
System.out.println("Hi, " + name + "!");
} else {
System.out.println("Hello, " + name + "!");
}
}
}

说明:

  • 声明为final的方法不能被重载。
  • 声明为static的方法不能被重载,但是能够被再次声明。

5.对象

对象创建方式:类名 对象名 = new 类名()

Java虚拟机在创建一个对象时都包含以下步骤:

  • 给对象分配内存。
  • 将对象的实例变量自动初始化为其变量类型的默认值。
  • 初始化对象,给实例变量赋予正确的初始值。

注意:每个对象都是相互独立的,在内存中占有独立的内存地址,并且每个对象都具有自己的生命周期,当一个对象的生命周期结束时,对象就变成了垃圾,由Java虚拟机自带的垃圾回收机制处理。

匿名对象

通过前面的知识我们已经了解到了,每次new都相当于开辟了一个新的对象,并开辟了一个新的物理内存空间。如果一个对象只需要使用唯一的一次,就可以使用匿名对象,匿名对象还可以作为实际参数传递。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Person {
public String name; // 姓名
public int age; // 年龄

// 定义构造方法,为属性初始化
public Person(String name, int age) {
this.name = name;
this.age = age;
}

// 获取信息的方法
public void tell() {
System.out.println("姓名:" + name + ",年龄:" + age);
}

public static void main(String[] args) {
new Person("张三", 30).tell(); // 匿名对象 => 姓名:张三,年龄:30
}
}

6.抽象类

由于多态的存在,每个子类都可以覆写父类的方法,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Person {
public void run() { … }
}

class Student extends Person {
@Override
public void run() { … }
}

class Teacher extends Person {
@Override
public void run() { … }
}

定义:
抽象类:抽象方法所在的类,必须是抽象类才行,在class前写上abstract即可
抽象方法:就是在方法强加上abstract关键字,然后去掉大括号,直接分号结束

使用方法:

  1. 不能直接创建new抽象类对象
  2. 必须用一个子类来继承抽象父类
  3. 子类必须覆盖重写抽象父类当中的所有抽象方法
  4. 创建子类实例对象进行使用
    如果一个class定义了方法,但没有具体执行代码,这个方法就是抽象方法,抽象方法用abstract修饰。因为无法执行抽象方法,因此这个类也必须申明为抽象类(abstract class)。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29

    public class OOP{
    public static void main(String[] args) {
    /*
    *这里值得值得注意:用abstract修饰的类就是抽象类。我们无法实例化一个抽象类
    */
    Person p = new Student(); // 第四点:创建子类实例对象
    p.age = 18;
    p.run();

    }
    }

    // 抽象类不仅要在类名前加abstract,也要在抽象方法名前加abstract
    // Person类用abstract修饰的,表示为抽象类,我们无法实例化抽象类
    abstract class Person{
    protected int age;
    public abstract void run();

    }

    // Student类继承Person类,并将父类的run方法进行重写
    class Student extends Person{
    @Override
    public void run(){
    System.out.println(super.age); // super指代父类
    System.out.println(this.age);
    }
    }
    小结:
  • 通过abstract定义的方法是抽象方法,它只有定义,没有实现。抽象方法定义了子类必须实现的接口规范;

  • 定义了抽象方法的class必须被定义为抽象类,从抽象类继承的子类必须实现抽象方法;

  • 抽象类无法被实例化(即className 变量名 = new className())

7.接口

含义

如果一个抽象类没有字段或者说没有属性,所有方法全部都是抽象方法【抽象方法:修饰符 abstract 返回值类型 方法名()】,就可以把该抽象类改写为接口:interface

1
2
3
4
5
6
// 抽象类
abstract class Person {
public abstract void run();
public abstract String getName();
public abstract String getName();
}

在Java中,可以使用interface可以声明一个接口:

1
2
3
4
interface Person{
void run();
String getName();
}

所谓interface,就是比抽象类还要抽象的纯抽象接口,因为它连字段都不能有。因为接口定义的所有方法默认都是public abstract的,所以这两个修饰符不需要写出来(写不写效果都一样)

实现方式

当一个具体的class去实现一个interface时,需要使用implements关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Student implements Person {
private String name;

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

@Override
public void run() {
System.out.println(this.name + " run");
}

@Override
public String getName() {
return this.name;
}
}

类实现多接口

在Java中,一个类只能继承自另一个类,不能从多个类继承。但是,一个类可以实现多个interface

1
2
3
class Student implements Person, Hello { // 实现了两个interface
...
}

接口继承

一个interface可以继承自另一个interface。interface继承自interface使用extends,它相当于扩展了接口的方法。例如:

1
2
3
4
5
6
7
8
interface Hello {
void hello();
}

interface Person extends Hello {
void run();
String getName();
}

此时,Person接口继承自Hello接口,因此,Person接口现在实际上有3个抽象方法签名,其中一个来自继承的Hello接口。

8.package包

Java包的命名规范:

  • 包名全部由小写字母(多个单词也全部小写)
  • 如果包名包含多个层次,每个层次用“.”分割
  • 包名一般由倒置的域名开头,比如com.baidu,不要有www
  • 自定义包不能java开头
1
2
3
4
5
6
7
8
9
10
程序目录结构:
package_sample
└─ src
├─ com.hong
│ └─ Person.java
│ com.ming
│ └─ Person.java
└─ com.mr
└─ jun
└─ Arrays.java

使用import导入相关包

  • 方式一:import 包名.某一类名
  • 方式二:import 包名.*

 评论

联系我 | Contact with me

Copyright © 2019-2020 谁知你知我,我知你知深。此恨经年深,比情度日久

博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议