java三大特性分别是封装,继承,多态。
封装:将对象的状态信息隐藏在对象内部,而外部无法直接访问,必须通过对象来访问(直观点就是将成员变量及方法写在class xxx{ }里面)
比如Person类
public class Person
{
private int id;
private int age;
private String name;
public int getId()
{
return id;
}
public void setId(int id)
{
this.id=id;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age=age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name=name;
}
}
这就是一个非常简单的具有封装特征的类(将成员变量以及对成员变量的操作即方法写在一个类中)。
封装的主要优点:
1.对外隐藏实现的具体细节
2.让使用者只能通过事先预订的方法来访问数据,这样可以在方法中添加适当的控制逻辑,限制不合法的访问
3.进行数据检查,保证数据的完整性
4.便于修改,具有良好的可维护性
继承:顾名思义,子类拥有父类的属性和方法,比如父亲拥有一笔财产,儿子继承父亲的财产,儿子就可以直接使用父亲的财产
java中继承使用extends关键字来实现,并且注意java是单继承的,为什么要使用继承呢?引用别人书上的一个例子自己稍微改变一下来说明:
我们要开发一款游戏(就比如DNF,哈哈以前高中时玩过,现在基本没怎么玩游戏了,事业为重是吧),dnf里有很多角色,比如剑圣,狂战,魔法师,他们都有很多
共同的属性,比如等级level,名称nmae,血量blood等,如果没有继承,那么每一个角色都要声明这些成员变量,如果有100个角色,岂不是要重复100次吗?
但是有了继承,我只需要父类Role声明这些成员变量,并提供相应的访问方法,那么子类继承这个父类Role,子类就拥有这些成员变量及方法,而不需要自己一直复制粘贴到死
下面是这个例子的简单代码,能够说明一些问题:
public class Role
{
private int level;
private String name;
private int blood;
public void setLevel(int level)
{
this.level=level;
}
public int getLevel()
{
return level;
}
public void setName(String name)
{
this.name=name;
}
public int getName()
{
return name;
}
public void setBlood(int blood)
{
this.blood=blood;
}
public int getBlood()
{
return blood;
}
}
public class JianSheng extends Role
{
public void fight()
{
System.out.println("剑圣fight");
}
}
public class KuangZhan extends Role
{
public void fight()
{
System.out.println("狂战fight");
}
}
public class Main
{
public static void main(String[] args)
{
JianSheng jiansheng=new JianSheng();
jiansheng.setLevel(45);//子类继承父类的方法,可以直接使用
jiansheng.setName("passion");
jiansheng.setBlood(100);
KuangZhan kuangzhan=new KuangZhan();
kuangzhan.setLevel(80);
kuanghzhan.setNmae("ipassion");
kaungzhan.setBlood(100);
}
}
上面这几段代码,JianSheng类中我们没有显示的声明int level;String name这些成员变量却可以使用setLevel(),setName()等方法,这是因为使用了extends关键字来继承父类Role,这样子类JianSheng和KuangZhan就拥有了这些成员变量及方法,而且子类除了继承父类的属性和方法外,我们还可以自己添加这个类额外独有的方法,比如上面的fight()方法就是我们在子类中单独添加的
另外还要注意的是父类的private成员变量虽然是私有的,但是子类依然继承下来了(某些书上说private的不能被继承),实际上子类继承父类后也拥有这些private的成员变量及方法,只是我们不能直接访问这些private的成员变量(如果需要子类能够直接访问,可以将父类的成员变量换成用protected访问修饰符修饰),但是我们可以通过setXxx(),getXxx()这些方法来访问
下面再来讨论继承的构造器运作方式,先来2段代码来说明情况:
public class Brid
{
protected String name;
public Brid(String name)
{
this.name=name;
}
public Brid copy()
{
return new Brid(name);
}
}
public class Chicken extends Brid
{
/***
* 如果父类定义了含参数的构造方法,子类继承父类,则子类必须重写父类的构造方法,并且显示调用父类的构造方法
* static方法不能被重写,因为static方法是类所有,而非对象
* 就算子类定义了与父类相同的static方法,但是也不能说子类该方法重写了父类的方法,该方法是仅仅子类新定义的,而非重写(与普通方法,没区别)
* @param name
*/
public Chicken(String name)
{
/**为什么此处必须是super(name)呢?
* 因为子类继承父类,在子类的构造方法中会默认调用父类的无参构造函数,
* 而父类Brid由于我们自己定义了public Brid(String name)的构造函数
* 编译器便不会帮我们自动生成无参的构造函数,这里隐式调用了父类的无参构造函数,
* 而父类却没有该构造函数,当然编译不通过啦
*
* super()如果出现,必须在构造器的第一行,绝对不能在在其他代码之后,
* 如果这里没有这段super(name);代码,实际上会默认调用无参数的父类构造方法即super()
*/
super(name);
System.out.println("hell world");
}
@Override
public Chicken copy()
{
return new Chicken(name);
}
public static void main(String[] args)
{
/**
* 首先new关键字告诉系统分配内存空间,进行初始化,这个对象已经产生(注意此时还没有调用Chicken的构造方法),
* 然后才开始调用Chicken类的构造函数,执行到super(name);会调用父类的带参数的构造方法,父类的构造函数里面的代码执行完成后,
* 才开始执行子类Chicken里的super(name)之后的代码,执行完成之后,返回当前对象的引用
*/
new Chicken("hello").copy();
}
}
未完待续....