Java基础(二)
目录
继承
使用关键字extends
来表示继承
比如:
经理是员工,而员工只是员工。
再比如
兔子和羊属于食草动物类,狮子和豹属于食肉动物类。
食草动物和食肉动物又是属于动物类。
所以继承需要符合的关系是:is-a,父类更通用,子类更具体。
虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。
public class Manager extends Employee{
add some methods and fields;
}
关键字
extends
表明正在构造的心类派生与一个已存在的类。
- 已存在的类称为超类、基类或父类
- 新类称为子类、派生类或孩子类
通过扩展超类定义子类的时候,只需要指出子类与超类的不同之处。因此在设计类的时候,应该将最一般的方法放在超类中,而将更特殊的方法放在子类中,这种将通用功能抽取到超类的做法在面向对象程序设计中十分普遍
特别注意,java中,不适用于多重继承,但是java中可以使用关键字
implements
实现多个接口
back
覆盖办法
在超类中的有些方法对子类不一定使用,对于上面的例子,员工和经理的工资的计算方法不一样,因此需要另一种的计算方式。这这,便是我们要说的覆盖方法。
看下面:
public class Employee{
private double salary;
public double getSalary(){
return salary;
}
}
这就是员工(employee)的工资,如果经理(manager)是在员工的基础上,加上一些其他的工资,那应该怎样写呢?
public Manager extends Employee{
private double bonus;
public double getSalary(){
return salary+bonus;//这并不工作
}
}
如果我们不考虑其他因素,是不是应该就如这样写?员工的工资加上自身的工资,就组成了经理的工资。但是像上面的,如果你这样做的话,肯定是不可以的。因为Manager类的getSalary方法是不可能直接访问Employee的salary字段,因为我用了private关键字。因此,要像其他的方法那样,使用公用接口,也就是在Employee里面写上getSalary方法。
而上面,我已经写了该方法,那么我们是不是可以这样来访问?
public Manager extends Employee{
private double bonus;
public double getSalary(){
double baseSalary=getSalary();
return bonus+baseSalary;
}
}
当然,你如果这样写的话,那么就会无线调用自己,从而导致程序崩溃
为此,我们可以采用super
关键字,这个关键字是调用父类中的方法,保证父类的方法能够正常运行,此时我们可以这样写:
public Manager extends Employee{
private double bonus;
public double getSalary(){
double baseSalary=super.getSalary();
return bonus+baseSalary;
}
}
back
super关键字
作用:
- 1 主要存在于子类方法中,用于指向子类对象中父类对象。
- 2 访问父类的属性
- 3 访问父类的函数
- 4 访问父类的构造函数
package Learn;
class test1{
int ans;
test1(int ans){
this.ans=ans;
}
}
public class Demo extends test1 {
int ans;
Demo(int ans1,int ans2){
//访问父类的构造函数
super(ans1);
this.ans=ans2;
}
int getFatherAns(){
//访问父类的值
return super.ans;
}
public static void main(String[] args) {
Demo d=new Demo(1,2);
System.out.println(d.ans);
System.out.println(d.getFatherAns());
}
}
back
使用子类构造器
class Employee{
private double salary;
//构造函数
public Employee(double salary){
this.salary=salary;
}
}
public class Manager extends Employee{
private double bonus;
public Manager(double salary,double bonus){
super(salary);
//使用super,即可调用父类的构造函数,使其初始化值
this.bonus=bonus;
}
}
back
多态
有一个简单的规则可以用来判断是否应该将数据设计为继承关系,这规则是is-a
规则。它指出子类的对象也是超类的对象。
下面引用动物,猫,狗的例子
猫能干啥呢?抓老鼠,吃鱼,对吧,狗呢,能吃骨头,看家。
下面我们使用了抽象类,猫和狗,抽象出来,都是动物吧,那么我们就把猫和狗抽象出来,他们都是动物。动物能干啥?能吃。所以添加了一个抽象的方法。
猫是动物么?is-a
原则,是!好,我们让Cat类继承Animal类
抽象方法是我们得去实现它,猫能吃啥?刚刚说了,猫能吃鱼。
对于狗,也一样,狗能吃啥?骨头。
对于猫和狗,他们有自己的功能吧,那么猫能抓老鼠,狗能看家。
//抽象类
abstract class Animal{
//抽象方法
abstract void eat();
}
//继承
class Cat extends Animal{
public void eat(){
//猫吃鱼
System.out.println("吃鱼");
}
public void catchMouse(){
//猫能抓老鼠
System.out.println("抓老鼠");
}
}
class Dog extends Animal{
public void eat(){
//狗能吃骨头
System.out.println("吃骨头");
}
public void kanJia(){
//狗能看家
System.out.println("看家");
}
}
class DuoTaiDemo{
//这是一个多态的样理
public static void main(String[] args){
function(new Cat());//这里是创建一个对象,创建猫这个对象
function(new Dog());//创建狗这个对象
//Animal是父类,那么我们在父类的基础上,申请了一个猫,这样是可以的,因为猫是动物,动物能做的东西,猫肯定能做。
//换句话来理解就是,父类往往都是一些通用的东西,而子类往往都是父类的派生,功能更加强大。
Animal a = new Cat();//向上转型
a.eat();
Cat c = (Cat)a;//向下转型
c.catchMouse();
}
public static void function(Animal a){
a.eat();
//用于子类型有限
//或判断所属类型进而使用其特有方法
if(a instanceof Cat){
//使用instanceof关键字,判断是什么类,如果是猫类,那么转换
Cat c = (Cat)a;
c.catchMouse();
}
else if(a instanceof Dog)
{
Dog c = (Dog)a;
c.kanJia();
}
}
}
back
instanceof关键字
Java中的instanceof
运算符是用来在运行时指出对象是否是特定类的一个实例
。instanceof
通过返回一个布尔值
来指出,这个对象是否是这个特定类或者是它的子类的一个实例。
它的语法是:
object instanceof constructor
-
object
object是某个实例对象 -
constructor
constructor是某个构造函数
back
interface关键字
在抽象类中,可以包含一个或多个抽象方法;但在接口(interface)中,所有的方法必须都是抽象的,不能有方法体,它比抽象类更加“抽象”。
接口使用 interface 关键字来声明,可以看做是一种特殊的抽象类,可以指定一个类必须做什么,而不是规定它如何去做。
比如你的电脑的STAT接口,他不规定你干啥,你有下个对应的东西插上就可以用了
- 接口中只能定义抽象方法,这些方法默认为 public abstract 的。
- 接口中没有构造方法,不能被实例化。
- 一个接口不实现另一个接口,但可以继承多个其他接口。
- 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类(abstract)是可以有静态代码块和静态方法。
back
equals()方法和toString()方法
有的时候需要重写equals方法或者toString方法,这个方法在你创建类的时候,就已经存在了,是系统给你写好的。有的时候确实是要重写这两个方法
原型:
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
@Override
public String toString() {
return super.toString();
}
为什么会存在这两个方法呢?
我们在编写我们的类的时候,总是会继承Object类,这是java的规则。可以说,Object是所有类的超类,如果我们使用instanceof
去与Object
比较,返回的值必定是正确的。
back
异常、断言
在一个理想的世界中,用户的所有的格式都是对的,文件也一定能够打开,代码永远不会出现bug。但是现实世界中,你永远都是在打bug.....
Java异常机制用到的几个关键字:
关键字 | 作用 |
---|---|
try | 用于监听,主要是可能抛出异常的语句块中,当发生异常的时候,就会抛出 |
catch | 用于捕获异常,捕获try语句中的异常 |
finally | finally语句块总是会被执行的,主要是用于回收资源,比如你打开了数据库的连接,出现了异常,你得关闭,不然会浪费巨大的计算机资源。如果finally中使用了return或者throw等终止方法的语句,直接停止 |
throw | 抛出异常,本层抛出异常,可本层处理,也可返回上一层处理 |
throws | 抛出异常,用在方法签名中,声明该方法能够返回异常,移交上一层处理 |
例子:
package Learn;
public class Test{
void function1(int a,int b){
int c;
try{
c=a/b;
System.out.println(c);
}catch (Exception e){
System.out.println("函数一发生了异常,非法错误");
}
finally {
System.out.println("实验一异常,finally字段");
}
System.out.println("实验一结束");
}
void function2(int a,int b){
int c;
try{
if(b==0)
throw new Exception();
c=a/b;
System.out.println(c);
}catch (Exception e){
System.out.println("函数二发生了异常,非法错误");
}
finally {
System.out.println("实验二异常,finally字段");
}
System.out.println("实验二结束了");
}
void function3(int a,int b)throws Exception{
int c;
if(b==0)
throw new Exception();
c=a/b;
System.out.println(c);
}
public static void main(String[] args) {
int a=1;
int b=0;
Test t=new Test();
t.function1(a,b);
t.function2(a,b);
try {
t.function3(a,b);
}catch (Exception e){
System.out.println("主函数接收到异常");
}
finally {
System.out.println("主函数接收到异常,finally字段");
}
System.out.println("主函数结束了");
}
}
back
参考《Java核心技术卷一》
大部分是个人思想,如果不对,请指正
如果转载,请标明出处