面向对象的三大特征-继承

今天学习了面向对象的三大特征的第二特征-继承,了解了继承的特点。根据继承的特点编写了一些小程序,实验了继承语法的一些特点

继承

继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。语法extends

public class Person {
    
    
private String name;
protected int age;
public String getName() {
    
    
return name;
}
public void setName(String name) {
    
    
this.name = name;
}
}
public class Student extends Person {
    
    
private double score;
}
//调用测试
Student s=new Student();
s.setName("yanjun");
s.age=100;

继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。
继承是is-a的相互关系
私有属性是否可被继承—两种答案
这个问题目前没有唯一的标准答案,网络上可以看到2种答案,分别是可继承和不可继承

  • 可以被继承,但是由于private的限制,所以在子类中不能直接访问

  • 不可以被继承。当构建子类对象时,首先创建父类对象,然后再创建子类对象,子类对象中包裹父类对象

子类除了拥有父类的属性和方法(拥有父类的所有成员,但是注意构造器和析构器不是成员),也可以创建自己的特性

继承的特点

  • Java中不支持多重继承,Java中要求任何的子类只能有一个直系的双亲类
public class Student extends Person,Random{
    
    
// 语法报错,
//多重继承原因:因为多继承容易出现问题。
//两个父类中有相同的方法,子类到底要执行哪一个是不确定的
//如果定义类但是没有extends,则意味着默认父类为java.lang.Object。
//这也就是说Java中的任意类都是Object的子类
}
public class Student {
    
    
public static void main(String[] args) {
    
    
Student s1=new Student();
System.out.println(s1.toString());
}
}
  • 可以在子类中进行覆盖定义父类中的成员方法和成员属性
public class Person {
    
    
public boolean sex=false;
public void pp() {
    
    
System.out.println("this is Person.pp");
}
}
public class Student extends Person{
    
    
String sex="男";//属性的覆盖
public void pp() {
    
     //方法的覆盖
System.out.println("this is student.pp");
}
public static void main(String[] args) {
    
    
Student s1=new Student();
System.out.println(s1.sex);
s1.pp();
}
}
  • Java支持多层继承(继承体系):C继承B,B继承A,就会出现继承体系。Java中的所有类都直接或者间接的集成于java.lang.Object类
  • 多层继承出现的继承体系中,通常看父类中的功能,了解该体系的基本功能,建立子类对象,即可使用该体系功能
  • Object obj=new Student();语法正确,但是只能调用Object类中的所有方法
    定义继承需要注意:不要仅为了获取其他类中某个功能而去继承,类与类之间要有所属( “is a”)关系

继承的优点

  • 将所有子类的共同属性放入父类,实现代码共享,避免重复,提高开发效率

  • 可以使得修改扩展,继承而来的实现比较简单

继承的缺陷

  • 父类变,子类就必须变
  • 继承破坏了封装,对于父类而言,它的实现细节对与子类来说都是透明的
  • 继承是一种强耦合关系
    继承的编码问题
public class Person {
    
    
public Person() {
    
    
System.out.println("Person....");
}
}
public class Student extends Person{
    
    
public Student() {
    
    
System.out.println("student....");
}
public static void main(String[] args) {
    
    
Student s1=new Student();
}
}
//实际输出值为:
//Person....
//student....

结论:上溯流程中先查找所有的父类,然后才从根类开始逐层调用构造器

public class A{
    
    
private A(){
    
    } // 由于只有一个私有构造器,所以A类不能被继承
}

继承的语意是is a,所以【父类 obj=new 子类()】,比如Person p=newStudent();
对农场中所有的农副产品排序
采用冒泡排序,但是不同的产品比较方法不一致,使用父类定义排序算法的实现,但是没有办法定义的比较可以延迟到子类中实现。

public class BubbleSorter {
    
    
	public void sort(Object[] arr) {
    
     // 排序算法的实现
		for (int i = 1; i < arr.length; i++) {
    
    
			for (int k = 0; k < arr.length - i; k++) {
    
    
				if (bigger(arr[k], arr[k + 1])) {
    
    
					Object temp = arr[k];
					arr[k] = arr[k + 1];
					arr[k + 1] = temp;
				}
			}
		}
	}

	public boolean bigger(Object obj1, Object obj2) {
    
     // 比较算法,这里仅仅只是一个桩
		return true;
	}
}
public class PigSorter extends BubbleSorter {
    
    
	public boolean bigger(Object obj1, Object obj2) {
    
    
		if (obj1 != null && obj2 != null) {
    
    
			if (obj1 instanceof Pig && obj2 instanceof Pig) {
    
    
				Pig p1 = (Pig) obj1;
				Pig p2 = (Pig) obj2;
				return p1.getWeight() > p2.getWeight();
			}
		}
		return true;
	}
}
public class Pig {
    
    
	private double weight;
	private String color;

	public double getWeight() {
    
    
		return weight;
	}

	public void setWeight(double weight) {
    
    
		this.weight = weight;
	}

	public String getColor() {
    
    
		return color;
	}

	public void setColor(String color) {
    
    
		this.color = color;
	}

	@Override
	public String toString() {
    
    
		return "Pig [weight=" + weight + ", color=" + color + "]";
	}
}

java.lang.Object
所有Java类都直接或者间接的继承自Object类,那么Object中的方法也是其他有类都拥有的
Object类中的常用方法
getClass方法用于获得当前对象的类型

Student s1=new Student();
System.out.println(s1.getClass());
//输出结果为 class com.yan2.Student

直接输出一个对象时,实际上默认输出的是该对象toString()方法的返回值。所有的Java类中都有这个方法,因为Java类都直接或者间接的继承于Object类,而

Object类中定义了toString方法
public String toString() {
    
    
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
// 输出内容是getClass()获取类型,再调用getName()获取类型名称,例如com.yan2.Student
//hashCode方法是Object类中定义的一个方法,Object类定义的方法默认用于获取当前对象存储地址相关的一个
//整数,Integer.toHexString用于将整数转换为1进制字符串
System.out.println(new Random())实际显示为java.util.Random@6d06d69c

为了实现用户自定义输出格式,允许在类中覆盖定义toString方法

public String toString() {
    
    
     return "Pig [weight=" + weight + ", color=" + color + "]";
}
在Object类中有equals方法的定义
 	public boolean equals(Object obj) {
    
    
          return (this == obj); //实际上在Object中定义的equals比较的是对象的引用值
}
Student s1=new Student(); s1.setId(1L);
Student s2=new Student(); s2.setId(1L);
System.out.println(s1==s2);
System.out.println(s1.equals(s2));//因为equals是通过Object继承到的方法,所以这里的equals的实现原理还是==比较

如果需要修改比较规则,则需要在Student类中重新覆盖定义equals方法,例如比较规则为id

public class Student {
    
    
	private Long id;

	public boolean equals(Object obj) {
    
    
		if (obj != null && obj instanceof Student) {
    
    
			Student temp = (Student) obj;
			long k1 = id.longValue();// 代码不够完善,因为调用方法前没有判null
			long k2 = temp.getId().longValue();
			return k1 == k2;
		}

hashCode()方法返回一个整形数值,表示该对象的哈希码值
源代码

public native int hashCode(); //native表示该方法使用C/C++通过对等类的方式实现
Student s1=new Student();
System.out.println(s1.hashCode()); //366712642
  • 如果两个对象相等(依据:调用equals()方法),那么这两个对象调用hashCode()返回的哈希码也必须相等
  • 两个对象调用hasCode()返回的哈希码相等,这两个对象不一定相等

特殊关键字

什么是包

  • 包是类的组织方式,提供名空间和访问控制
  • 类似于文件系统的组织
    声明包中的类package
    语法:package 包名称;
  • 声明包要求是源代码文件的第一个语句
  • 程序中最多只能有一条package语句,没有包定义的源代码文件成为默认包中的一部分
  • 程序中如果有package语句,该语句必须是第一条语句(前面只能有注释或空行)
    包的作用
  • 包能将相关的源代码文件组织在一起
  • 包减少了名称冲突带来的问题
  • 可以使用package指明源文件中的类属于哪个具体的包
    包的使用
  • 如果其他人想使用包中类,则需要使用全名
  • 为了简化书写,Java提供了import语句: import package_name.*;
  • 引入包中的某一个类:import java.util.ArrayList;
    引入包import
  • Java缺省引入的包为java.lang
  • 引入包中的类: import 包名称.类名称;例如import java.util.Date;
  • 引入整个包; import 包名称.* ;例如 import java.util.* ;
  • 不引入包而是用类,则需要是用类的全名: 包名.类名,例如java.util.Date dd=new java.util.Date();
    包的文件组织和类路径CLASSPATH
    在类路径中定义包的位置
  • 代表当前目录,为默认值
  • 类文件存放的位置:类路径中的目录\包名称对应的路径
  • 缺省包default package
  • 源代码文件中没有package语句声明,且类文件位于CLASSPATH所定义的目录中
  • 满足以上条件的所有类被认为处在同一个包中,这个包被称为缺省包

Classpath描述了Java虚拟机在运行一个Class时在哪些路径中加载要运行的类以及运行的类要用到的类。当一个程序找不到他所需的其他类文件时,系统会自动到CLASSPATH环境变量所指明的路径中去查找第三方提供的类和用户定义的类
Java中常用的包

  • java.applet用于提供Applet开发的支持,目前已经被Öash所替代,很少使用,只有在某些地图系统中还有使用
  • java.awt和javax.swing用于单机软件或者c/s应用中的界面开发
  • java.io用于输入、输出操作
  • java.lang语言包,默认自动加载的包
  • java.net用于网络编程
  • java.util工具包,是Java提供的一些工具类

猜你喜欢

转载自blog.csdn.net/Lecheng_/article/details/112686160