抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

类与对象

类可以看成是具有很多相似性质、功能的事物的集合,如鸟可以看作一个类,鸟都具有各自的名称,各色的羽毛、飞等相似特点;

用代码创建一个鸟类:

1
2
3
4
5
6
7
public class Bird{
String name;
String feathers_color;
public void fly(){
System.out.println(name + "可以飞")
}
}

对象可以看作是类的一个具体事例,如上面所说的鸟类,鸽子是鸟类的一种,老鹰也是鸟类一种,因此鸽子、老鹰都可以分别看作是鸟类的一个对象;

用代码来创建对象:

1
2
Bird bird1 = new Bird();
Bird bird2 = new Bird();

引用与指向

在下面创建的这一对象中

1
Bird bird1 = new Bird();

bird1存储的是对象的地址,因此bird1是对象的引用;这一地址指向了对象本身;

image-20210123153305198
  • 多个引用指向同一对象
1
2
3
Bird b1 = new Bird();
Bird b2 = b1;
Bird b3 = b1;
image-20210123154400728
  • 多个引用指向多个(不同)对象
1
2
3
Bird b1 = new Bird();
Bird b2 = new Bird();
Bird b3 = new Bird();
image-20210123154635298

继承

可以创建两个类,其中一个类可以继承另一个类的属性和方法,继承语法:

1
2
3
public class ClassName2 extends ClassName1{

}

例如:

首先创建父类Item

1
2
3
4
public class Item {
String name;
int price;
}

创建子类Weapon继承Item

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Weapon extends Item{
int damage; //攻击力

public static void main(String[] args) {
Weapon infinityEdge = new Weapon();
infinityEdge.damage = 65; //damage属性在类Weapon中新设计的

infinityEdge.name = "无尽之刃";//name属性,是从Item中继承来的,就不需要重复设计了
infinityEdge.price = 3600;

}

}

方法重载

方法的重载指的是方法名一样,但是参数类型或数量不一样

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
public class ADHero extends Hero {
//无参数
public void attack() {
System.out.println(name + " 进行了一次攻击 ,但是不确定打中谁了");
}

//1个参数
public void attack(Hero h1) {
System.out.println(name + "对" + h1.name + "进行了一次攻击 ");
}

//2个参数
public void attack(Hero h1, Hero h2) {
System.out.println(name + "同时对" + h1.name + "和" + h2.name + "进行了攻击 ");
}

public static void main(String[] args) {
ADHero bh = new ADHero();
bh.name = "赏金猎人";

Hero h1 = new Hero();
h1.name = "盖伦";
Hero h2 = new Hero();
h2.name = "提莫";

bh.attack(h1);
bh.attack(h1, h2);
}

}

可变数量的参数

采用可变数量的参数 只需要设计一个方法
public void attack(Hero... heros)
即可代表上述所有的方法了,此时 heros被当作一个数组,在方法里,使用操作数组的方式处理参数heros即可

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 ADHero extends Hero {

public void attack() {
System.out.println(name + " 进行了一次攻击 ,但是不确定打中谁了");
}

// 可变数量的参数
public void attack(Hero... heros) {
for (int i = 0; i < heros.length; i++) {
System.out.println(name + " 攻击了 " + heros[i].name);

}
}

public static void main(String[] args) {
ADHero bh = new ADHero();
bh.name = "赏金猎人";

Hero h1 = new Hero();
h1.name = "盖伦";
Hero h2 = new Hero();
h2.name = "提莫";

bh.attack(h1);
bh.attack(h1, h2);

}

}

构造方法

构造方法是一个特殊的方法,其方法名与类名一样,没有返回类型,在实例化一个对象时,必然调用构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Hero {

String name;

float hp;

float armor;

int moveSpeed;

// 方法名和类名一样(包括大小写)
// 没有返回类型
public Hero() {
System.out.println("实例化一个对象的时候,必然调用构造方法");
}

public static void main(String[] args) {
//实例化一个对象的时候,必然调用构造方法
Hero h = new Hero();
}

}

//输出:实例化一个对象的时候,必然调用构造方法

构造方法也可以重载,即可以有几个构造方法,但它们的参数数量或类型不同

this

this 代表当前对象,因此把this看成一个对象就行,对象的属性、方法、构造方法它都有

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
34
35
36
37
38
public class Hero {

String name; //姓名

float hp; //血量

float armor; //护甲

int moveSpeed; //移动速度

//打印内存中的虚拟地址
public void showAddressInMemory(){
System.out.println("打印this看到的虚拟地址:"+this);
}

public static void main(String[] args) {
//---------------------------------------------
Hero garen = new Hero();
garen.name = "aaa";
System.out.println("打印对象看到的虚拟地址:"+garen);
garen.showAddressInMemory();

//-------------------------------------------
Hero teemo = new Hero();
teemo.name = "bbb";
System.out.println("打印对象看到的虚拟地址:"+teemo);
teemo.showAddressInMemory();
}

}

//输出:
/*
打印对象看到的虚拟地址:Hero@2a139a55
打印this看到的虚拟地址:Hero@2a139a55
打印对象看到的虚拟地址:Hero@15db9742
打印this看到的虚拟地址:Hero@15db9742
*/

通过this 可以访问对象的属性、方法

通过this()可以调用其他的构造方法

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
34
35
36
37
38
public class Hero {

String name; // 姓名

float hp; // 血量

float armor; // 护甲

int moveSpeed; // 移动速度

// 带一个参数的构造方法
public Hero(String name) {
System.out.println("一个参数的构造方法");
this.name = name;
}

// 带两个参数的构造方法
public Hero(String name, float hp) {
this(name);
System.out.println("两个参数的构造方法");
this.hp = hp;
}

public static void main(String[] args) {
Hero teemo = new Hero("aaaa", 383); //两个参数

System.out.println(teemo.name);

}

}

/*输出:

一个参数的构造方法
两个参数的构造方法
aaaa
*/

传参

  • 基本类型传参与引用类型传参

    基本类型传参,不多说

    引用类型传参,即传入参数为引用类型

  • =的含义

    • 如果变量是基本类型,则 =表示赋值

    • 如果变量是引用类型,= 表示指向的意思,比如

      1
      Hero h = new Hero();  //引用h,指向一个Hero对象
  • 引用类型传参

    形参与实参都指向同一对象

    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 Hero {

    String name;

    float hp;

    public Hero(String name, float hp) {
    this.name = name;
    this.hp = hp;
    }

    public void attack(Hero hero) {
    System.out.println("hero:"+hero);
    }

    public static void main(String[] args) {
    Hero teemo = new Hero("teemo", 383);
    Hero garen = new Hero("garen", 616);
    garen.attack(teemo);
    System.out.println("teemo:"+teemo);

    }

    }

    /**输出:
    hero:Hero@2a139a55
    teemo:Hero@2a139a55
    */

    用图表示如下image-20210123184909979

    但如果形参在内部指向了新的对象,实参是不会跟着改变的

    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
    public class Hero {

    String name; // 姓名

    float hp; // 血量

    public Hero(String name, float hp) {
    this.name = name;
    this.hp = hp;
    }

    public void attack(Hero hero) {
    hero = new Hero("hero", 100); //形参指向了新的对象
    System.out.println("hero:"+hero);
    }

    public static void main(String[] args) {
    Hero teemo = new Hero("teemo", 383);
    Hero garen = new Hero("garen", 616);
    garen.attack(teemo);
    System.out.println("teemo:"+teemo);

    }

    }

    /**输出:
    hero:Hero@2a139a55
    teemo:Hero@15db9742
    */

    用图表示如下image-20210123185224792

类属性(又叫静态属性)

当一个属性被static修饰的时候,就叫做类属性,又叫做静态属性
当一个属性被声明成类属性,那么所有的对象,都共享一个值

对象属性: 又叫实例属性,非静态属性

与对象属性对比:
不同对象的 对象属性 的值都可能不一样。

  • 访问类属性:

    1
    类.类属性
    1
    2
    //访问对象属性:
    对象.对象属性
  • 类属性与对象属性的选择

    • 如果一个属性,每个英雄都不一样,比如name,这样的属性就应该设计为对象属性,因为它是跟着对象走的,每个对象的name都是不同的
    • 如果一个属性,所有的英雄都共享,都是一样的,那么就应该设计为类属性。比如血量上限,所有的英雄的血量上限都是 9999,不会因为英雄不同,而取不同的值。 这样的属性,就适合设计为类属性

类方法(静态方法)

类方法: 又叫做静态方法,即被static修饰的方法

对象方法: 又叫实例方法,非静态方法

区别:

调用一个对象方法,必须建立在有一个对象的前提的基础上
调用类方法,不需要对象的存在,直接就访问

  • 调用类方法

    1
    类.类方法
    1
    2
    //访问对象方法
    对象.对象方法
  • 什么时候用类方法

    如果一个方法,没有调用任何对象属性,那么就可以考虑设计为类方法,比如:

    1
    2
    3
    public static void printGameDuration(){
    System.out.println("已经玩了50秒");
    }

    反之,如果方法里访问了对象属性,那么这个方法,就必须设计为对象方法;

    注意:类方法中不能直接调用对象方法

评论