第二学时 类和对象
什么是类,什么是对象?
这是大家一开始学习最头疼的问题。教科书上的定义是类是一个抽象概念,对象是类的一个实例。但这不太好理解。下面通过一个例子来简单说明。
首先电脑是一个类,因为电脑是一个抽象概念,那什么叫做抽象概念。其实很简单,电脑是一个统称。如果我问你电脑多少钱,那你们肯定无法回答,因为你不知道我具体只哪台电脑,联想,索尼还是苹果?因为不是一个具体的实例,所以电脑是一个类。
那假如我问某台电脑是不是一个类?答案肯定是不是一个类。因为某一台电脑具体指某一个实例。
这时我问这台电脑多少钱你们就能回答我。所以具体的某一台电脑是一个对象。
总的来说,类是一个泛指,他是一些具有相同属性的对象的总称,而对象则是类的一个具体特指。
下面来说说类的一些特征:
用前面的例子。电脑具有什么特征?
1.价格 2.品牌 3.外观......
其次,电脑还具有一些功能
1.办公 2.玩游戏....
在java中也类似,每一个类都具有自己的属性(及上面说到的特征)
每一个类都有自己的方法(及上面说的功能)
定义一个类
public class 类名{
属性
方法
}
如:
public class Computer{
private String brand;//定义一个品牌属性
private double price;//定义一个价格属性
public void play(){
......//定义一个play方法
}
}
补充一个知识点,一个.java文件中只能有一个public类,也就是说可以有多个类,但前面不能加public,但不建议这样作,最好是一个文件一个类(内部类除外)。
实例化一个类:
类名 对象名 = new 类名();
Computer com = new Computer();
方法调用:
com.play();//调用play()方法,用法与c语言中结构类型相似
又有同学会问,为什么不能直接使用play(),这就体现了面向对象编程思想,具体到是哪个对象调用了哪个方法。
构造方法:
在类中分为普通方法和构造方法。
其中,普通方法已经介绍过了,下面来看看构造方法。
构造方法是用来实例化对象和初始化对象的,
如 Student stu = new Student();
其中Student(),就是构造方法,当使用new时会在堆(heap)中开辟一个内存,接着,Student()
构造方法会在开辟的内存里面写入类的属性和方法,最后返回一个地址给stu。
那么,问题就来了,有的同学会问,既然Student()是构造方法,但我在;类里面没有写这个构造方法,为什么能调用?原因是java中,如果没有写构造方法,那么系统会默认调用一个构造方法。
构造方法的定义:
public 类名(数据类型 形参名,...){
方法。。。
}
这里要注意的是,构造方法中没有数据类型返回(包括void也不能有),还有一点,如果已经定义一个构造方法,则系统不再调用默认构造方法。
方法重载:
条件:
1.方法名字要完全一样
2.方法带的参数类型,个数,顺序不完全一样
这也就是说,返回值类型无影响
如:public void fun(){}
public void fun(int a){}//这两个是方法在重载
public void fun(){}
public void fun(){}//这两个不是方法在重载
this关键字:
this 顾名思义即是指这个,也就是当前对象。
如 Student类中有name属性,那么this.name 则表示当前对象的name。
this还有另一种用法
public Student(String name){
。。。
}
public Student(){
this(“。。”); // 构造方法里面使用this()指的是调用当前对象的另一个构造方)
} //前提是有这个构造方法
传值与传引用:
学过c语言的同学都知道,所谓传值,则是传实参的一个副本,形参的改变不影响实参。传地址则会影响实参,因为下一种指向实参的地址,会改变实参的值。
java中没有指针的说法,但传引用与传指针类似。
如 public static void main(String[] args){
Student stu = new Student();
int a=10;
fun(a,stu);
}
public static void fun(int a , Student stu){
stu.setName("..");
a=19;
}//这个例子中 a传的是指,而stu传的是引用,那么fun()中改变的a不会影响main()中的a,而//fun()中改变的name,会影响main()中stu里面的name。因为stu传递的是地址
有的同学可能会问,既然传的是地址,那么干嘛不干脆叫传指针,改名传引用。其实这个问题我也想过,学习过c#得同学会跟清楚,这里我只做简单介绍。因为c语言中的指针是直接对内存进行操作,这样的话对于程序来说是不安全的,严重的可能使程序崩溃,而面向对象中有一个思想即是对数据的封装,这样会增加程序的安全性。所以指针的使用违背的面向对象编程思想,所以在java中禁止了指针的使用.
实例:编写一个英雄类与一个Boss类,实现双方的战斗
public class Hero { private int blood; private int harm; private String name; /** * 构造方法,初始化name,harm,blood属性 * @param name * @param harm * @param blood */ public Hero(String name,int harm,int blood){ this.name=name; this.harm=harm; this.blood=blood; } public Hero(){ this("",0,0); } /** * 定义一个获得血量方法 * @return 血量 */ public int getBlood() { return blood; } /** * 定义一个设置血量方法,当血量少于0时,血量设为0 * @param blood */ public void setBlood(int blood) { if(blood<0){ this.blood=0; }else{ this.blood = blood; } } /** * 定义一个获得伤害方法 * @return 血量 */ public int getHarm() { return harm; } /** * 定义一个设置血量方法 * @param blood */ public void setHarm(int harm) { this.harm = harm; } /** * 定义一个获得名字方法 * @return 血量 */ public String getName() { return name; }/** * 定义一个设置血量方法 * @param blood */ public void setName(String name) { this.name = name; } /** * 定义一个攻击方法 */ public void attack(Boss b){ b.setBlood(b.getBlood()-harm); } }
/** * 定义一个Boss类 * @author chenzhaomin * */ public class Boss { private int blood; private int harm; private String name; /** * 构造方法,初始化name,harm,blood属性 * @param name * @param harm * @param blood */ public Boss(String name,int harm,int blood){ this.name=name; this.harm=harm; this.blood=blood; } public Boss(){ this("",0,0); } /** * 定义一个获得血量方法 * @return 血量 */ public int getBlood() { return blood; } /** * 定义一个设置血量方法 * @param blood */ public void setBlood(int blood) { if(blood<0){ this.blood=0; }else{ this.blood = blood; } } /** * 定义一个获得伤害方法 * @return 血量 */ public int getHarm() { return harm; } /** * 定义一个设置血量方法 * @param blood */ public void setHarm(int harm) { this.harm=harm; } /** * 定义一个获得名字方法 * @return 血量 */ public String getName() { return name; }/** * 定义一个设置血量方法 * @param blood */ public void setName(String name) { this.name = name; } /** * 定义一个攻击方法 */ public void attack(Hero h){ h.setBlood(h.getBlood()-harm); } }
import java.util.Random; public class Fight { /**主函数 * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Hero h = new Hero("德玛西亚",10,100);//实例化一个Hero对象 Boss b = new Boss("男爵",10,100);//实例化一个Boss对象 startFight(h,b);//调用战斗方法 } /** * 定义一个战斗方法 * @param h * @param b */ public static void startFight(Hero h,Boss b){ Random r = new Random();//定义一个随机数 /** * 利用随机数来确定谁开始战斗,循环战斗 */ while(true){ boolean bool = r.nextBoolean(); System.out.println(h.getName() + "HP = " + h.getBlood() + " \t " + b.getName() + "HP = " + b.getBlood()); if(bool){ h.attack(b); if(b.getBlood()==0){ System.out.println(h.getName() + " win!");//显示获胜者 return ; } }else{ b.attack(h); if(h.getBlood()==0){ System.out.println(b.getName() + " win!");//显示获胜者 return ; } } } } }
总结:类似一个统称,对象是一个实例。在面向对象编程中,必须要清楚具体是哪个对象调用了哪个方法