一、Object类
Object类是所有Java类的根基类(“祖先类”)
如果在类的声明中未使用extends关键字指明基类,则默认基类为Object类
public class Person{
}
等价于:
public class extends Object{
}
1、toString()方法
(1)Object类中定义有public String toString()方法,其返回值是String类型,描述当前对象的有关信息。
如果直接打印某对象的引用,则默认会调用这个对象的toString()方法,默认打印的内容中包含这个引用所指向的内存地址。
(2)可以根据需要在用户自定义类中重写toString()方法。
2、equals()方法
(1)Object类中定义有public boolean equals(Object obj)方法,提供定义对象是否“相等”的逻辑。
(2)Object的equals方法定义为:x.equals(y),当x和y指向同一个地址时返回true,否则返回false。
(3)String类中已经重写了equals(Object obj)方法,重写后的方法比较的是两个字符串的“内容”是否一样(注意:==比较对象的引用)。
(4)可以根据需要在用户自定义类型中重写equals方法。
package object;
public class Student {
private String name;
private int age;
private double score;
public Student() {
}
public Student(String name, int age, double score) {
super();
this.name = name;
this.age = age;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
}
}
package object;
public class ToStringDemo {
public static void main(String[] args) {
Student stu = new Student("小明",17,78);
System.out.println(stu);
}
}
运行结果:
Student [name=小明, age=17, score=78.0]
package object;
public class EqualsDemo {
public static void main(String[] args) {
Student stu1 = new Student("李明",18,88.5);
Student stu2 = new Student("李明",18,88.5);
System.out.println("stu1和stu2相等吗?" + stu1.equals(stu2));
}
}
运行结果:
stu1和stu2相等吗?false
二、多态性
封装是为了保护属性的一种操作,继承是为了扩展类的功能
是由封装性和继承性引出的面向对象程序设计语言的另一种特征
多态的体现
1、从方法的角度来看:
方法的重载与重写
(1)重载(overloading):根据传入的参数不同,完成功能也不同
(2)重写(override):子类根据需求重写父类中的方法。
2、从对象的角度来看:
对象的多态性主要分为两种:
(1)向上转型:子类对象->父类对象(程序会自动完成)
格式:
父类对象=子类实例
向上转型后,因为操作的是父类对象,所以无法找到在子类中定义的新方法;但如果子类重写了父类的某个方法,则调用的是重写后的方法。
(2)向下转型:父类对象->子类对象(必须明确的指明要转型的子类类型)
格式:
子类对象 = (子类)父类实例
注意:向下转型前先要向上转型
实例1:向上转型
package duotai.upper;
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public void say() {
System.out.println("我是父类方法say(),姓名:"+this.name+",年龄:"+this.age);
}
public void learn() {
System.out.println("我是父类的learn()方法,人学习...");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package duotai.upper;
public class Student extends Person{
private double score;
public Student() {
}
public Student(String name,int age,double score) {
super(name,age);
this.score = score;
}
@Override
public void learn() {
System.out.println("学生学习...");
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
}
package duotai.upper;
public class TestUpper {
public static void main(String[] args) {
Student stu = new Student("小明",17,83.5);
Person per = stu;//向上转型
per.say();
per.learn();
}
}
运行结果:
我是父类方法say(),姓名:小明,年龄:17
学生学习...
实例2:向下转型
package duotai.down;
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public void say() {
System.out.println("我是父类方法say(),姓名:"+this.name+",年龄:"+this.age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package duotai.down;
public class Student extends Person{
private double score;
public Student() {
}
public Student(String name,int age,double score) {
super(name,age);
this.score = score;
}
public void learn() {
System.out.println("学生学习...");
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
}
package duotai.down;
public class TestDown {
public static void main(String[] args) {
Person per = new Student("小明",22,89.5);//向上转型
Student stu = (Student)per;//向下转型
stu.learn();
stu.say();
}
}
运行结果:
学生学习...
我是父类方法say(),姓名:小明,年龄:22
instanceof关键字
1、在Java中可以使用instanceof关键字判断一个对象是否属于一个类的实例
1、格式:
对象 instanceof 类 -> 返回boolean类型
实例:
package instanceofdemo;
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public void say() {
System.out.println("我是父类方法say(),姓名:"+this.name+",年龄:"+this.age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package instanceofdemo;
public class Student extends Person{
private double score;
public Student() {
}
public Student(String name,int age,double score) {
super(name,age);
this.score = score;
}
public void learn() {
System.out.println("学生学习...");
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
}
package instanceofdemo;
public class Farmer extends Person{
public Farmer() {
}
public Farmer (String name,int age) {
super(name, age);
}
public void plant() {
System.out.println("农民种地...");
}
}
package instanceofdemo;
public class InstanceofDemo {
public static void main(String[] args) {
Student stu = new Student();
Farmer f = new Farmer();
method(null);
method(stu);
method(f);
System.out.println("*******************");
Person p = new Student();
System.out.println(p instanceof Person);//判断是否是Person类型
System.out.println(p instanceof Student);//判断是否是Student类型的对象转换过来的
}
public static void method(Person per) {
if(per == null) {
System.out.println("不能直接传递null");
return;
}
if(per instanceof Student) {
Student stu = (Student)per;
stu.learn();
}
if(per instanceof Farmer) {
Farmer f = (Farmer)per;
f.plant();
}
}
}
运行结果:
不能直接传递null
学生学习...
农民种地...
*******************
true
true
final关键字
1、在Java中声明类、属性和方法时,可以使用关键字final来修饰。
2、注意:
(1)final修饰变量(成员变量或局部变量),则成为常量,只能复制一次
final 类型 variableName;
修饰成员变量时,定义时同时给出初始值,而修饰局部变量时不做要求。
(2)final修饰方法,则该方法不能被子类重写
final 返回值类型 methodName(paramList){
...
}
(3)final修饰类,则类不能被继承
final class finalClassName(
...
}
三、抽象类与接口
1、用abstract修饰的类即为抽象类
abstract class 抽象类名{
}
2、抽象类不能被实例化,必须被继承,抽象方法必须被重写,生成它的子类;
3、由abstract修饰的方法就是抽象方法,抽象方法没有方法体;
4、抽象类不一定要包含抽象方法,若类中包含了抽象方法,则该类必须被定义为抽象类;
5、如果一个子类没有实现抽象父类中所有的抽象方法,则子类也称为一个抽象类;
6、构造方法、静态方法、私有方法、final方法不能被声明为抽象的方法。
实例:
package abstractdemo;
public abstract class Animal {
private String name;
private String food;
public Animal() {
}
public Animal(String name, String food) {
this.name = name;
this.food = food;
}
//抽象方法只声明,不实现
public abstract void eat();
}
package abstractdemo;
public class Cat extends Animal {
private String fur;
public Cat() {
}
public Cat(String name, String food, String fur) {
super(name, food);
this.fur = fur;
}
@Override
public void eat() {
System.out.println("小猫吃鱼...");
}
public String getFur() {
return fur;
}
public void setFur(String fur) {
this.fur = fur;
}
}
package abstractdemo;
public class Dog extends Animal {
private String color;
public Dog() {
}
public Dog(String name, String food, String color) {
super(name, food);
this.color = color;
}
@Override
public void eat() {
System.out.println("小狗啃骨头...");
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
package abstractdemo;
//如果子类也是一个抽象类,则可以不用重写父类的抽象方法
public abstract class Tiger extends Animal {
public abstract void run();
}
package abstractdemo;
public class TestAnimal {
public static void main(String[] args) {
Animal animal1 = new Cat();//由猫对象向上转型
Animal animal2 = new Dog();//由狗对象向上转型
animal1.eat();
animal2.eat();
}
}
运行结果:
小猫吃鱼...
小狗啃骨头...
接口
1、接口(interface)是抽象方法和常量值的定义的集合;
2、接口是一种“标准”、“契约”;
3、从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。
接口的声明语法
1、包括接口声明和接口体
2、完整的接口声明:
[public] interface 接口名称[extends listOfSuperInterface] { ... }
3、接口体包括常量定义和方法定义
(1)常量定义:type Name = value; 该常量被实现该接口的多个类共享;具有public、final、static的属性
(2)方法体定义:具有public和abstract属性
接口的实现类
1、与抽象类一样,接口要使用也必须通过子类,子类通过implements关键字实现接口;
2、一个类可以实现多个接口,在implements子句中用逗号隔开;
3、非抽象子类必须实现接口中定义的所有方法;
4、实现格式:
class 子类 implements 接口A,接口B,...{}
接口的使用规则
1、接口中所有的方法都是public abstract;
2、在接口中声明方法时,不能使用static、final、synchronized、private、protected等修饰符;
3、一个接口可以继承自另一个接口;
4、Java中不允许类的多继承,但允许接口的多继承;
5、接口中可以有数据成员,这些成员默认都是public static final。
接口的用途
用处
1、通过接口实现不相关类的相同行为,而无需考虑这些类之间的关系;
2、通过接口指明多个类需要实现的方法;
3、通过接口了解对象的交互界面,而无需了解对象所对应的类。
实例:
package interfacedemo;
/**
* 飞翔接口
*/
public interface Fly {
public static final int SPEED = 200;
public abstract void fly();
}
package interfacedemo;
/**
* 散步接口
*/
public interface Walk {
public void walk();
}
package interfacedemo;
public class Bird implements Fly,Walk {
@Override
public void fly() {
System.out.println("小鸟飞翔...");
}
@Override
public void walk() {
System.out.println("小鸟散步...");
}
}
package interfacedemo;
public class Kite implements Fly {
@Override
public void fly() {
System.out.println("风筝飞翔...");
}
}
package interfacedemo;
public class Test {
public static void main(String[] args) {
Fly f1 = new Kite();
f1.fly();
Fly f2 = new Bird();
f2.fly();
Walk w = new Bird();
w.walk();
}
}
运行结果:
风筝飞翔...
小鸟飞翔...
小鸟散步...