0%

面向对象

面向对象

继承

举例

1
2
3
4
5
6
7
8
9
10
11
12
package Object_oriented.inheritance;

public class Weapon extends Item{
int damage;

public static void main(String[] args) {
Weapon infinityEdge = new Weapon();
infinityEdge.damage = 65;
infinityEdge.name = "无尽之刃";
infinityEdge.price = 3600;
}
}

方法重载:方法名一样,但是参数类型不一样

采用可变数量的参数 只需要设计一个方法 public void attack(Hero ...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);

}

}

构造方法

通过一个类创建一个对象,这个过程叫做实例化

实例化是通过调用构造方法(又叫做构造器)实现的

定义:

方法名和类名一样(包括大小写) 没有返回类型 实例化一个对象的时候,必然调用构造方法

隐式的构造方法

无参的构造方法,如果不写,就会默认提供一个

如果提供了一个有参的构造方法,同时又没有显式的提供一个无参的构造方法那么默认的无参的构造方法,就“木有了“

构造方法的重载

this的使用

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
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 = "盖伦";
//直接打印对象,会显示该对象在内存中的虚拟地址
//格式:Hero@c17164 c17164即虚拟地址,每次执行,得到的地址不一定一样

System.out.println("打印对象看到的虚拟地址:"+garen);
//调用showAddressInMemory,打印该对象的this,显示相同的虚拟地址
garen.showAddressInMemory();

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

}

输出:

1
2
3
4
打印对象看到的虚拟地址:Object_oriented.reload.Hero@1b6d3586(和下面this引用的一样)
打印this看到的虚拟地址:Object_oriented.reload.Hero@1b6d3586
打印对象看到的虚拟地址:Object_oriented.reload.Hero@4554617c
打印this看到的虚拟地址:Object_oriented.reload.Hero@4554617c

通过this访问属性

关键代码

1
2
3
4
5
public void setName3(String name){
//name代表的是参数name
//this.name代表的是属性name
this.name = name;
}

完整代码:

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
39
40
41
42
public class Hero {

String name; //姓名

float hp; //血量

float armor; //护甲

int moveSpeed; //移动速度

//参数名和属性名一样
//在方法体中,只能访问到参数name
public void setName1(String name){
name = name;
}

//为了避免setName1中的问题,参数名不得不使用其他变量名
public void setName2(String heroName){
name = heroName;
}

//通过this访问属性
public void setName3(String name){
//name代表的是参数name
//this.name代表的是属性name
this.name = name;
}

public static void main(String[] args) {
Hero h =new Hero();

h.setName1("teemo");
System.out.println(h.name);

h.setName2("garen");
System.out.println(h.name);

h.setName3("死歌");
System.out.println(h.name);
}

}

输出

1
2
3
null
garen
死歌

通过this调用其他的构造方法

关键代码

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

完整代码

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
package Object_oriented.reload;

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("提莫",383);
System.out.println(teemo.name);
}

}

传参

基本类型传参

基本类型传参 在方法内,无法修改方法外的基本类型参数

关键代码

1
2
3
4
5
6
7
int xueping = 100;

//提莫通过这个血瓶回血

teemo.huixue(xueping);

System.out.println(xueping);

完整代码

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

String name; //姓名

float hp; //血量

float armor; //护甲

int moveSpeed; //移动速度

public Hero(){

}

//回血
public void huixue(int xp){
hp = hp + xp;
//回血完毕后,血瓶=0
xp=0;
}

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

public static void main(String[] args) {
Hero teemo = new Hero("提莫",383);
//血瓶,其值是100
int xueping = 100;

//提莫通过这个血瓶回血

teemo.huixue(xueping);

System.out.println(xueping);

}

}

输出

1
2
100
(按理说不应该是100,因为已经回血后按理说血瓶废了,说明方法没有修改方法外参数)

引用与=

如果一个变量是基本类型 比如 int hp = 50; 我们就直接管hp叫变量 =表示赋值的意思。 如果一个变量是类类型 比如 Hero h = new Hero(); 我们就管h叫做引用=不再是赋值的意思 =表示指向的意思 比如 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
public class Hero {

String name; // 姓名

float hp; // 血量

float armor; // 护甲

int moveSpeed; // 移动速度

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

// 攻击一个英雄,并让他掉damage点血
public void attack(Hero hero, int damage) {
hero.hp = hero.hp - damage;
}

public static void main(String[] args) {
Hero teemo = new Hero("提莫", 383);
Hero garen = new Hero("盖伦", 616);
garen.attack(teemo, 100);
System.out.println(teemo.hp);
}

}

输出

1
283.0

四种访问修饰符

成员变量有四种修饰符 private 私有的 package/friendly/default 不写 protected 受保护的 public 公共的

类之间的关系

类和类之间的关系有如下几种: 以Hero为例 自身:指的是Hero自己 同包子类:ADHero这个类是Hero的子类,并且和Hero处于同一个包下 不同包子类:Support这个类是Hero的子类,但是在另一个包下 同包类: GiantDragon 这个类和Hero是同一个包,但是彼此没有继承关系 其他类:Item这个类,在不同包,也没有继承关系的类

private 私有的

只能自己用

自身:是可以访问的 同包子类:不能继承 不同包子类:不能继承 同包类:不能访问 其他包类:不能访问

package/friendly/default 不写

只能在同一个包里用

### protected 受保护的

同一个包里和是它的子类都能用

public 公共的

谁都可以用

选择依据

  1. 属性通常使用private封装起来
  2. 方法一般使用public用于被调用
  3. 会被子类继承的方法,通常使用protected
  4. package用的不多,一般新手会用package,因为还不知道有修饰符这个东西

再就是作用范围最小原则 简单说,能用private就用private,不行就放大一级,用package,再不行就用protected,最后用public。 这样就能把数据尽量的封装起来,没有必要露出来的,就不用露出来

类属性、静态属性

当一个属性被static修饰的时候,就叫做类属性,又叫做静态属性 当一个属性被声明成类属性,那么所有的对象,都共享一个值 与对象属性对比: 不同对象的 对象属性 的值都可能不一样。 比如盖伦的hp 和 提莫的hp 是不一样的。 但是所有对象的类属性的值,都是一样的

类属性

类属性: 又叫做静态属性 对象属性: 又叫实例属性,非静态属性 如果一个属性声明成类属性,那么所有的对象,都共享这么一个值

举例

1
2
3
public String name; //实例属性,对象属性,非静态属性
protected float hp;
static String copyright;//类属性,静态属性

访问类属性

  1. 对象.类属性

    1
    teemo.copyright
  2. 类.类属性

1
Hero.copyright

类方法

类方法: 又叫做静态方法

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

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

类方法

举例

关键代码

1
2
3
4
5
6
7
8
9
10
11
//实例方法,对象方法,非静态方法
//必须有对象才能够调用
public void die(){
hp = 0;
}

//类方法,静态方法
//通过类就可以直接调用
public static void battleWin(){
System.out.println("battle win");
}

完整代码

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
package charactor;

public class Hero {
public String name;
protected float hp;

//实例方法,对象方法,非静态方法
//必须有对象才能够调用
public void die(){
hp = 0;
}

//类方法,静态方法
//通过类就可以直接调用
public static void battleWin(){
System.out.println("battle win");
}

public static void main(String[] args) {
Hero garen = new Hero();
garen.name = "盖伦";
//必须有一个对象才能调用
garen.die();

Hero teemo = new Hero();
teemo.name = "提莫";

//无需对象,直接通过类调用
Hero.battleWin();

}
}

调用类方法

  1. 对象.类方法

  2. 类.类方法

属性初始化

对象属性初始化

  1. 声明该属性的时候初始化
  2. 构造方法中初始化
  3. 初始化块

初始化块中的代码会先执行,接着是构造方法中的代码,最后是在属性声明时直接赋值的代码。

举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package charactor;

public class Hero {
public String name = "some hero"; //声明该属性的时候初始化
protected float hp;
float maxHP;

{
maxHP = 200; //初始化块
}

public Hero(){
hp = 100; //构造方法中初始化

}

}

类属性初始化

  1. 声明该属性的时候初始化
  2. 静态初始化块

举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package charactor;

public class Hero {
public String name;
protected float hp;
float maxHP;

//物品栏的容量
public static int itemCapacity=8; //声明的时候 初始化

static{
itemCapacity = 6;//静态初始化块 初始化
}

public Hero(){

}

public static void main(String[] args) {
System.out.println(Hero.itemCapacity);
}

}

单例模式

单例模式又叫做 Singleton模式,指的是一个类,在一个JVM里,只有一个实例存在。

饿汉式单例模式

  1. 通过私有化其构造方法,使得外部无法通过new 得到新的实例。
  2. 私有实例化一个对象
  3. 定义一个公共的类方法用于返回之前创建的对象

关键:无论如何都会创建一个实例

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package charactor;

public class GiantDragon {

//私有化构造方法使得该类无法在外部通过new 进行实例化
private GiantDragon(){

}

//准备一个类属性,指向一个实例化对象。 因为是类属性,所以只有一个

private static GiantDragon instance = new GiantDragon();

//public static 方法,提供给调用者获取12行定义的对象
public static GiantDragon getInstance(){
return instance;
}

}

懒汉式单例模式

使用:

  1. 私有化构造方法
  2. 准备一个私有的类属性,但是暂时只想NULL
  3. 定义一个公共的类方法,如果之前私有的类属性指向空,就实例化一个对象,否则就不用

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package charactor;

public class GiantDragon {

//私有化构造方法使得该类无法在外部通过new 进行实例化
private GiantDragon(){
}

//准备一个类属性,用于指向一个实例化对象,但是暂时指向null
private static GiantDragon instance;

//public static 方法,返回实例对象
public static GiantDragon getInstance(){
//第一次访问的时候,发现instance没有指向任何对象,这时实例化一个对象
if(null==instance){
instance = new GiantDragon();
}
//返回 instance指向的对象
return instance;
}

}

单例模式三元素

  1. 构造方法私有化
  2. 静态属性指向实例
  3. public static的 getInstance方法,返回第二步的静态属性

枚举类型

预先定义的常量

注:因为是常量,所以一般都是全大写

举例:

1
2
3
public enum Season {
SPRING,SUMMER,AUTUMN,WINTER
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class HelloWorld {
public static void main(String[] args) {
Season season = Season.SPRING;
switch (season) {
case SPRING:
System.out.println("春天");
break;
case SUMMER:
System.out.println("夏天");
break;
case AUTUMN:
System.out.println("秋天");
break;
case WINTER:
System.out.println("冬天");
break;
}
}
}

遍历枚举

增强型for循环

1
2
3
4
5
6
7
public class HelloWorld {
public static void main(String[] args) {
for (Season s : Season.values()) {
System.out.println(s);
}
}
}