在 Java 中,类和类之间是单继承的,一个类只能有一个父类,即 Java 中不支持多继承 ,但是 一个类可以实现多个接 口 。下面通过类来表示一组动物 .
public abstract class Animal {
public String name;
public int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public abstract void eat();
}
public interface IRunning {
void run();
}
public interface ISwimming {
void swim();
}
public interface IFlying {
void fly();
}
public class Dog extends Animal implements IRunning,ISwimming{
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(name+"吃狗粮!");
}
@Override
public void run() {
System.out.println(name+"用狗腿在跑");
}
@Override
public void swim() {
System.out.println(name+"用狗腿游泳");
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Bird extends Animal implements IRunning,IFlying{
public Bird(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(name+"吃鸟粮");
}
@Override
public void fly() {
System.out.println(name+"用翅膀飞");
}
@Override
public void run() {
System.out.println(name+"用鸟腿跑");
}
}
public class Test {
public static void test1(Animal animal) {
animal.eat();
}
public static void test2(IRunning iRunning) {
iRunning.run();
}
public static void test3(ISwimming iSwimming) {
iSwimming.swim();
}
public static void test4(IFlying iFlying) {
iFlying.fly();
}
public static void main(String[] args) {
test1(new Dog("狗",4));
test2(new Dog("狗",4));
test3(new Dog("狗",4));
System.out.println("=====================");
test1(new Bird("鸟",2));
test2(new Bird("鸟",2));
test4(new Bird("鸟",2));
}
}
注意:一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类 。
上面的代码展示了 Java 面向对象编程中最常见的用法 : 一个类继承一个父类 , 同时实现多种接口
在 Java 中,类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承。即:用接口可以达到多继承的目的。
接口可以继承一个接口 , 达到复用的效果 . 使用 extends 关键字 .
public interface IRunning {
void run();
}
public interface ISwimming {
void swim();
}
public interface IFlying extends IRunning,ISwimming{
void fly();
}//继承了两个接口还可以有自己的接口
1.接口中的成员都被public static final修饰,而抽象类中的可以有普通成员.
2.接口中的方法默认被public abstract修饰,而抽象类中的方法可以是抽象的也可以是非抽象的.
3.一个类可以继承一个类并执行多个接口,接口之间只有extends关系.
给对象数组排序实例:
实例化两个学生对象,比较大小并将其排序.
按照我们之前的理解, 数组我们有一个现成的 sort 方法,sort依据数值大小可以排序,但不能用来排两个学生的顺序,学生的大小关系需要我们额外指定变量(名字长度,年龄大小还是身高等等).
我们先来比较学生对象的大小,再利用冒泡排序排好
class Student implements Comparable<Student>{
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
/*法一:
if(this.age > o.age) {
return 1;
}else if(this.age < o.age) {
return -1;
}else {
return 0;
}*/
//法二:
return this.age - o.age;
}
}
//比较年龄大小
class AgeComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
}
//比较名字拼音长度
class NameComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}
}
public class Test {
public static void bubbleSort(Comparable[] comparable) {
for (int i = 0; i < comparable.length - 1; i++) {
NameComparator nameComparator = new NameComparator();
for (int j = 0; j < comparable.length - 1 - i; j++) {
if(nameComparator.compare((Student) comparable[j], (Student)comparable[j+1]) > 0) {
Comparable tmp = comparable[j];
comparable[j] = comparable[j+1];
comparable[j+1] = tmp;
}
}
}
}
public static void main(String[] args) {
Student student1 = new Student("zhangsan",10);
Student student2 = new Student("lisi",15);
System.out.println(student1);
System.out.println(student2);
System.out.println("===============");
System.out.println(student1.compareTo(student2));
Student[] student = new Student[3];
student[0] = new Student("zhangsan",10);
student[1] = new Student("lisi",2);
student[2] = new Student("wangwu",18);
bubbleSort(student);
System.out.println(Arrays.toString(student));
}
}
Java 中内置了一些很有用的接口 , Clonable 就是其中之一 .
Object 类中存在一个 clone 方法 , 调用这个方法可以创建一个对象的 " 拷贝 ". 但是要想合法调用 clone 方法 , 必须要 先实现 Clonable 接口 , 否则就会抛出 CloneNotSupportedException 异常 .
我想拷贝一份person对象,但发现clone方法不能直接调用.如下:
class Person {
int age;
public Person(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
}
public class Test2 {
public static void main(String[] args) {
Person person1 = new Person(3);
Person person2 = person1.clone();
}
}
在person类当中重写clone方法:
class Person {
int age;
public Person(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Test2 {
public static void main(String[] args) {
Person person1 = new Person(3);
Person person2 = person1.clone();//仍就调用不了clone方法
}
}
分析解决:
正确代码:
class Person implements Cloneable{
int age;
public Person(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Test2 {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person(3);
Person person2 = (Person)person1.clone();
}
}
那么什么是浅拷贝呢?
在上述代码的基础上我定义一个类Money,在这个类中定义成员money = 14.3.
class Person implements Cloneable{
int age;
public Money m;
public Person(int age) {
this.age = age;
this.m = new Money();
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
//克隆方法在Object当中,并且由protected修饰,所写类默认继承Object类
//protected:不同包中的子类.同时使用时,需要super调用
public class Test2 {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person(3);
Person person2 = (Person)person1.clone();
System.out.println(person1.m.money);//14.3
System.out.println(person2.m.money);//14.3
System.out.println("=========================");
person2.m.money = 99.0;
System.out.println(person1.m.money);//99.0
System.out.println(person2.m.money);//99.0
//person2.m.money = 99.0;这句代码原本应该是只改变person2.m.money的值,但是person1也改变了
}
}
原因:
那怎么实现只改变person2中的money值?代码如下:
class Person implements Cloneable{
int age;
public Money m;
public Person(int age) {
this.age = age;
this.m = new Money();
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person tmp = (Person)super.clone();
tmp.m = (Money)this.m.clone();//克隆的返回值类型为Object需要强转
return tmp;
}
}
//克隆方法在Object当中,并且由protected修饰,所写类默认继承Object类
//protected:不同包中的子类.同时使用时,需要super调用
public class Test2 {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person(3);
Person person2 = (Person)person1.clone();
System.out.println(person1.m.money);
System.out.println(person2.m.money);
System.out.println("=========================");
person2.m.money = 99.0;
System.out.println(person1.m.money);
System.out.println(person2.m.money);
}
}
//双击shift 搜Object
Object 是 Java 默认提供的一个类。 Java中, Object 类是所有类的父类(哪怕没有写明extends Object),默认会继承 Object 父类。即所有类的对象都可以使用Object 的引用进行接收。
代码示例:
class Person{
}
class Student{
}
public class Test {
public static void main(String[] args) {
function(new Person());
function(new Student());
}
public static void function(Object obj) {
System.out.println(obj);
}
}
//执行结果:
Person@1b6d3586 Student@4554617c
对于整个Object类中的方法需要实现全部掌握。
如果要打印对象中的内容,可以直接重写 Object 类中的 toString() 方法,
class Person{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//1.重写了父类Object中的toString方法,
2.System.out.println(person);person处,父类引用,调用的是子类对象,最终成功打印出想要的子类(向上转型)
发生了动态绑定
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person("小吴",21);
System.out.println(person);
}
}
在 Java 中, == 进行比较时:
a. 如果 == 左右两侧是基本类型变量,比较的是变量中值是否相同
b. 如果 == 左右两侧是引用类型变量,比较的是引用变量地址是否相同
c.如果要比较对象中内容,必须重写Object中的equals方法,因为equals方法默认也是按照地址比较的:
当比较对象为引用类型对象并且不止一个时:
class Person{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
}
public class Test {
public static void main(String[] args) {
Person person1 = new Person("小吴",21);
Person person2 = new Person("小吴",21);
System.out.println(person1);
System.out.println(person2);
/*Object中,equals的方法为:
public boolean equals(Object obj) {
return (this == obj);
}*/
System.out.println(person1 == person2);
System.out.println(person1.equals(person2));
//所以在子类还未重写equals方法时,上述两行代码是一样的,无法正确比较
System.out.println("重写equals方法后:");
System.out.println(person1.equals(person2));//得到正确的比较结果
}
}
结论:比较对象中内容是否相同的时候,一定要重写 equals 方法。