Java-面向对象

文章目录

  • Day07
    • 7.1 面向对象概念
      • 面向对象
      • 面向过程
      • 对象
      • 类与对象之间的关系
    • 7.2 编写类的操作步骤
    • 7.3 编写测试类
    • 7.4 创建对象
    • 7.5 访问对象中的属性和方法
    • 7.6 成员变量和局部变量的区别
    • 7.7 对对象中的属性赋值
    • 7.8 构造方法以及重载
  • Day08
    • 8.1变量按数据类型分为
    • 8.2空指针异常
    • 8.3当一个对象中的属性是引用类型的案例
    • 8.4封装
      • 面向对象有三大特征:
      • 封装
    • 8.5this关键字
  • Day09
    • 9.1参数传递
      • 基本数据类型作为参数传递
      • 引用数据类型作为参数传递
    • 9.2static关键字
    • 9.3什么是继承
    • 9.4继承好处
    • 9.5编写继承代码步骤
    • 9.6 继承中注意事项
    • 9.7 重写

Day07

7.1 面向对象概念

面向对象

虚拟世界模拟现实生活,必须保证模拟一致

面向过程

对同一类事物的抽象的描述,也就是:不是具体的
如:电脑类、水杯类、键盘类、人类

对象

万物皆对象,也就是说:具体的实例
我的电脑、张三的水杯
对象所做的事情称为方法或行为(不是属性)

类与对象之间的关系

  • 抽象和具体的关系
    描述对象的特征,称为属性,如:颜色、价格、尺寸。。。
    如对象张三:
      属性:名字、性别、身高、体重、。。。
      方法:学习、说话、吃饭、游泳、。。。
  • 将多个对象找到相同的属性和方法组合在一起,形成类

7.2 编写类的操作步骤

第一步:编写类
语法格式:

[修饰符] class 类名{

}

第二步:编写属性
语法格式:

[修饰符] 数据类型 属性名称 [=值];
  • []中的内容是可有可无的
  • 属性名称也是标识符,建议采用驼峰命名法,见名知义
  • 当属性或成员变量没有赋值时,则有默认值的,数据类型不同则默认值不同:
      整数类型默认0
      浮点类型默认为0.0
      字符类型默认值为\u0000
      布尔类型默认值为false
      所有引用类型为null

第三步:编写方法
语法格式:

[修饰符] 返回类型 方法名称([参数列表]){
	方法体
}
  • 方法必须编写在类中
  • 在面向对象时,方法的修饰符暂时编写为public

7.3 编写测试类

也就是包含main方法的类
Test

7.4 创建对象

创建对象也叫做实例化
语法格式:

类名 引用名称 = new 类名(); 

一个类可以创建N个对象

//第一步:编写类
class Student{
	//第二步:编写属性也叫成员变量或实例(对象)变量,如果有属性类型相同建议分开写 
	String name;//默认值为null
	int age;//默认值为0
	char sex;//默认值为\u0000
	String address;//默认值为null
	
	//第三步:编写方法
	public void study(){
		System.out.println("正在学习面向对象课程。。。。");
	}
}

Java-面向对象_第1张图片

7.5 访问对象中的属性和方法

访问对象的中的属性:
 引用名称.属性名称
访问对象中的方法:
语法格式:引用名称.方法名称();
Java-面向对象_第2张图片

//第一步:编写类
class Student{
	//第二步:编写属性也叫成员变量或实例(对象)变量,如果有属性类型相同建议分开写 
	String name;//默认值为null
	int age;//默认值为0
	char sex;//默认值为\u0000
	String address;//默认值为null
	
	//第三步:编写方法
	public void study(){
		System.out.println("正在学习面向对象课程。。。。");
	}
}

//编写学生的测试类
class StudentTest{
	public static void main(String[] args){
		//根据类来创建对象,右侧对象地址赋给引用名称zs
		Student zs = new Student();//创建Student对象,同时在堆内存中开辟一块空间
		
		//通过引用名称zs获取对象中的属性
		System.out.println(zs.sex);
		
		//对对象的属性进行赋值,如:引用名称.属性名称 = 值
		zs.name = "张三";
		zs.age = 19;
		zs.sex = '男';
		zs.address = "北京市大兴区";
		
		//输出引用名称zs对应对象中所有属性的值
		System.out.println("姓名:"+zs.name+"\n年龄"+zs.age+"\n性别"+zs.sex+"\n地址"+zs.address);
		
		//使用引用名称访问对象中的方法,语法格式:引用名称.方法名称();
		zs.study();
		
		//创建第二个学生对象
		Student s = new Student();
		System.out.println(s.name);
		s.study();
	}
}

综合案例:

/**
 * 编写电脑类,属性:品牌、颜色、价格。方法:显示电脑信息
 * 编写电脑测试类,创建电脑对象,输出电脑信息
 */
class Computer{
	//属性也叫成员变量或者实例变量
	String brand;//null
	String color;//null
	double price;//0.0
	
	//方法
	public void show(){
		//注意本类中的成员变量可以在本类中任意位置直接使用
		System.out.println("品牌:"+brand+"\n颜色:"+color+"\n价格:"+price);
	}
}

//编写电脑测试类
class ComputerTest{
	public static void main(String[] args){
		//创建电脑对象也叫实例化
		Computer c = new Computer();
		//对引用名称中所有的属性进行赋值
		c.brand = "Lenovo";
		c.color = "black";
		c.price = 4999.9;
		c.show();
	}
}

7.6 成员变量和局部变量的区别

  • 声明位置不同:
      成员变量:在类中声明
      局部变量:在方法中声明,其中形参也属于局部变量
  • 初始值不同:
      成员变量:在没有赋值时,是有默认值的,数据类型不同,默认值不同
      局部变量:没有默认值,也就是说必须先声明,任何再赋值,最后才使用
  • 同一个类中,成员变量的名字可以和局部变量的名字同名,但是局部变量名字优先,也就是就近的优先,如果非要访问成员变量,必须加this.
/*
 * 编写车类,属性:颜色、品牌、价格
 * 编写车的测试类,创建车的对象
 */
class Car{
	//属性也叫成员变量
	String color;
	String brand;
	int price;
	
	//方法
	public void print(String name){//name是形参,也属于局部变量
		int i;//i就是局部变量
		
		for(int j = 1;j<=5;j++){//j也属于局部变量
			
		}
	}
	
	public void show(){
		int a;//a是局部变量
		//System.out.println("a = "+a);//出现编译错误,原因是局部变量必须先声明再赋值最后才使用
		a = 123;
		System.out.println("a = "+a);
		System.out.println("price = "+price);//0
	}
	
	public void print2(){
		//同一个类中,成员变量的名字可以和局部变量的名字同名,但是局部变量名字优先,也就是就近的优先
		//如果非要访问成员变量,必须加this.
		String color = "灰色";//color是局部变量
		System.out.println("输出局部变量color的值:"+color);
		System.out.println("输出成员变量color的值:"+this.color);
		//this代表当前这个对象,也就是当前谁(c)调用这个方法则这个对象就是谁
	}
	
	public void setBrand(String brand){//brand是形参,属于局部变量
		//将局部变量brand的值赋给成员变量brand
		this.brand = brand;
		
	}
}
//编写车的测试类
class CarTest{
	public static void main(String[] args){
		//实例化车
		Car c = new Car();
		c.print2();//灰色
		
		Car c3 = new Car();
		c3.setBrand("大众");
		System.out.println("品牌:"+c3.brand);
	}
}

7.7 对对象中的属性赋值

  • 第一种方法:完成对对象中的属性赋值:“引用名称.属性名称 = 值”
  • 第二种方法:完成对对象中的属性赋值,使用构造方法完成

7.8 构造方法以及重载

  • 作用:完成对对象的属性赋值

  • 构造方法:
      构造方法是一种特殊的方法,构造方法名字必须与类名一致
      构造方法没有返回类型,也就是不编写类型
      语法格式:public 方法名称([参数列表]){}

  • 构造方法时如何执行的?
      当创建对象时自动执行匹配的构造方法

  • 构造方法分类
      隐式构造方法:
        当在一个类中,没有手动编写构造方法,则系统会提供一个默认的无参的构造方法,即一个构造也没写
      显式构造方法:
        当在一个类中,手动编写构造方法,则系统不会提供默认的无参的构造方法
        建议当手动编写构造方法时,先编写无参构造方法,然后再编写需要的构造方法

  • 构造方法重载
      在同一个类中,构造方法的名字必须相同,参数列表不同(个数、类型、顺序不同)

/*
 * 编写狗类,属性:品种、颜色、名字、年龄、性别
 * 方法:输出狗的信息
 * 编写狗的测试类,实例化狗,调用狗的方法输出信息
 * */
class Dog{
	//构造方法
	public Dog(){//无参
		//完成对品种、颜色、名字、年龄、性别
		strain = "土狗";
		color = "黑色";
		name = "旺财";
		age = 5;
		sex = '公';
	}
	
	//带参构造方法,完成对属性品种、颜色、名字
	public Dog(String strain,String color,String name){
		//完成局部变量的值,赋给成员变量
		this.strain = strain;
		this.color = color;
		this.name = name;
	}
	
	//编写对所有属性的构造方法
	public Dog(String strain,String color,String name,int age,char sex){
		this.strain = strain;
		this.color = color;
		this.name = name;
		this.age = age;
		this.sex = sex;
	}
	
	//这是普通的方法,不是构造方法
	public void Dog(String name){
		this.name = name;
	}
	
	//属性也叫成员变量
	String strain;
	String color;
	String name;
	int age;
	char sex;
	//方法:输出狗的信息
	public void print(){
		System.out.println("品种:"+ strain +"\n颜色:"+color+"\n名字:"+name+"\n年龄:"+age+"\n性别:"+sex);

	}
}
//编写狗的测试类
class DogTest{
	public static void main(String[] args){
		//实例化狗
		Dog d = new Dog();
		
		//第一种方法:完成对对象中的属性赋值:“引用名称.属性名称 = 值”
		d.strain = "拉布拉多犬";
		d.color = "黄色";
		d.name = "小黄";
		d.age = 3;
		d.sex = '公';
		d.print();
		
		//第二种方法:完成对对象中的属性赋值,使用构造方法完成
		/*Dog d2 = new Dog();
		d2.print();
		
		System.out.println("--------------------");
		Dog d3 = new Dog();
		d3.print();*/
		
		//创建Dog对象同时执行带三个参数的构造方法
		Dog d4 = new Dog("泰迪","棕色","小迪");
		d4.print();
		
		//创建对象同时对所有属性赋值
		Dog d5 = new Dog("哈士奇","白色","二哈",4,'公');
		d5.print();
	}
}

Day08

8.1变量按数据类型分为

  • 基本数据类型:在内存中存放的是真正的值
    4大类共计8种
  • 引用数据类型:在内存中存放的是地址(引用)
    String,用户自定义类型,如:Student Computer
  • 对引用数据类型的赋值方式:
    • 第一种:将对象赋给引用名。如:s = new Student();
    • 第二种:将null值赋给引用名称。如:s = null;
//第一步:编写类
class Student{
	//属性 
	String name;
	int age;
	
	//方法
	public void print(){
		System.out.println("名字:"+name+"\n年龄:"+age);
	}
}

//编写学生的测试类
class StudentTest{
	public static void main(String[] args){
		//创建学生对象
		//Student s = new Student();
		//将上一条语句编写为如下两条语句
		Student s;//声明了一个局部变量s,也叫做引用名称s,当前s是Student类型,Student类型是用户自定义的类作为类型
		s = new Student();
		s = new Student();
		s = new Student();
		s = null;
		s.print();
		
		//int i = 10;
		int i;//i是局部变量,并且是整数类型
		i = 10;
		i = 123;
	}
}

Java-面向对象_第3张图片

8.2空指针异常

  • 属于运行错误,java.lang.NullPointerException
  • 原因:引用名称s是null,因此不能访问每个对象中的属性或方法,如果非要访问就会出现空指针异常
  • 解决办法:在调用某个对象中的属性或办法时,必须保证该引用名称中存放对象的地址(引用)
//第一步:编写类
class Student{
	//属性 
	String name;
	int age;
	
	//方法
	public void print(){
		System.out.println("名字:"+name+"\n年龄:"+age);
	}
}

//编写学生的测试类
class StudentTest{
	public static void main(String[] args){
		Student s;
		s = new Student();
		s.print();
		s = new Student();
		s.name = "张三";
		s.print();
		
		s = null;//s不能.age.name了
		//s.print();//出现运行错误,错误是空指针异常,
		//原因:引用名称s是null,因此不能访问每个对象中的属性或方法,如果非要访问就会出现空指针异常
		//解决办法:在调用某个对象中的属性或办法时,必须保证该引用名称中存放对象的地址
		
		s = new Student();
		s.print();
	}
}

Java-面向对象_第4张图片

8.3当一个对象中的属性是引用类型的案例

/*
 * 编程完成如下要求:
 * 	班级类:
 * 		属性:编号,名称,地址
 * 		定义:无参构造方法,有参构造方法
 * 		定义方法:显示班级信息
 * 学生类:
 * 		属性:学号,姓名,性别,年龄,所在班级
 * 		定义方法:显示学生的信息(学号,姓名,性别,年龄,班级编号,班级名称)
 * 
 * 		注意:所在班级应为班级类的类型
 * 测试类:
 * 		通过有参构造方法,创建班级对象
 * 		通过无参构造方法,创建学生类对象
 * 		调用显示信息的方法显示学生的信息
 * 
 * */

//编写班级类
class Grade{
	//属性:编号,名称,地址
	int num;
	String name;
	String address;
	
	//构造方法
	public Grade(){
		
	}//无参构造方法
	public Grade(int num,String name,String address){
		this.num = num;
		this.name = name;
		this.address = address;
	}
	//方法:显示班级信息
	public void show(){
		System.out.println("班级编号:"+num+"\n班级名称:"+name+"\n班级地址:"+address);
	}
}

//编写学生类
class Students{
	//属性:学号,姓名,性别,年龄,所在班级
	int id;
	String name;
	char sex;
	int age;
	Grade grade = new Grade();//grade是类中声明的成员变量,也叫局部变量,Grade类型
	//注意grade没有赋值时则默认值为null
	
	//方法:显示学生的信息(学号,姓名,性别,年龄,班级编号,班级名称)
	public void showInfo(){
		System.out.println("学生信息如下:");
		System.out.println("学号:"+ id+"\n姓名:"+name+"\n性别:"+sex+"\n年龄:"+age+
				"\n班级编号:"+grade.num+"\n班级名称:"+grade.name);
	}
}

//测试类
class Test{
	public static void main(String[] args){
		//通过有参构造方法,创建班级对象
		Grade grade = new Grade(431,"java基础班","四楼四教室");
		//通过无参构造方法,创建学生类对象
		Students s = new Students();
		//调用显示信息的方法显示学生的信息
		s.showInfo();
	}
}

Java-面向对象_第5张图片

8.4封装

面向对象有三大特征:

封装、继承和多态

封装

定义:
隐藏类的内部信息,不允许外部程序员直接访问,而是通过方法进行操作
封装操作步骤:

  • 第一步:将属性设置为私有的private,只能在本类中使用
  • 第二步:编写对应属性的赋值setXxx和取值getXxx方法
  • 第三步:根据情况编写判断语句
//第一步:编写类
class Student{
	//属性 
	String name;
	//第一步:将属性设置为私有的private,只能在本类中使用
	private int age;
	char sex;
	
	//第二步:编写对应属性的赋值setXxx和取值getXxx方法
	public void setAge(int age){
		//第三步:根据情况编写判断语句
		//将局部变量的值赋给成员变量,年龄0-100,否则为18
		if(age >= 0 && age <=100){
			this.age = age;
		}else{
			this.age = 18;
		}
	}
	public int getAge(){
		return age;//表示返回成员变量age的值
	}
}

//编写学生的测试类
class StudentTest{
	public static void main(String[] args){
		Student s;
		s = new Student();
		s.name = "张三";
		
		/*运行时发现有些属性如年龄性别不符合实际意义
		 * 解决办法:赋值之前进行判断,当前值如果合法则进行赋值,否则不赋值,称为封装
		 * */
		
		s.setAge(12345);
		
		System.out.println("\n年龄:"+s.getAge());
	}
}

封装综合案例:

/*
 * 编写学生类,属性:名字、年龄、性别
 * 要求:使用封装完成,对所有属性进行赋值和取值
 * 年龄:1-120,否则19
 * 性别:男、女,否则男
 * */
class Student1{
	//属性:
	private String name;
	private int age;
	private char sex;
	//编写所有属性的赋值setXxx
	public void setName(String name){
		this.name = name;
	}
	public void setAge(int age){
		//判断1-120
		if(age >= 1 && age <=120){
			this.age = age;
		}else{
			this.age = 19;
		}
	}
	public void setSex(char sex){
		//判断性别为男、女
		if(sex == '男' || sex == '女'){
			this.sex = sex;
		}else{
			this.sex = '男';
		}
	}
	//编写所有属性的赋值getXxx
	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}
	public char getSex(){
		return sex;
	}
}

//编写测试类
class Student1Test{
	public static void main(String[] args){
		//创建学生对象
		Student1 s = new Student1();
		//对所有属性赋值
		s.setName("李四");
		s.setAge(1234);
		s.setSex('a');
		//输出引用名称s中所有属性的值
		System.out.println("姓名:"+s.getName()+"\n年龄:"+s.getAge()+"\n性别:"+s.getSex());
	}
}

8.5this关键字

  • this表示当前这个对象,也就是说当前调用这个方法,则这个对象就是谁
  • this关键字可以访问本类中的实例变量
    • 当局部变量和成员变量没有同名时,则编写属性名等价于this.属性名,如:id等价于this.id
    • 当局部变量和成员变量同名时,并且访问成员变量则必须使用this.
  • this关键字可以访问本类中的实例方法
    • 方法名称([参数列表]);等价于this.方法名称([参数列表]);
  • this关键字可以访问本类中的其他构造方法
    • this();//访问本类无参构造方法
    • this([实参列表]);
    • 当使用this访问本类构造方法时,则只能编写在构造方法中的第一个语句
      构造方法不能出现递归调用
/*
编写车类,属性:车牌号、颜色、价格,方法:输出车的信息
编写车的测试类,创建车的对象,输出车的信息
*/
class Car{
	//构造方法
	public Car(){
		
	}
	//带参构造方法,完成对id和price赋值
	public Car(String id,int price){
		this.id = id;
		this.price = price;
	}
	//编写对所有属性赋值的构造方法
	/*public Car(String id,String color,int price){
		this.id = id;
		this.color = color;
		this.price = price;
	}*/
	//编写第二种带三个参数赋值的构造方法
	public Car(String id,String color,int price){
		//将局部变量id和price的值,给带两个参数的构造方法赋值
		this(id,price);//必须在构造方法中的第一个语句,构造方法不能自己调用自己
		this.color = color;
		//this(id,color,price);//构造方法不能出现递归调用
	}
	//属性
	String id;
	String color;
	int price;
	//方法
	public void print(){
		//在本类的方法中,可以直接访问本类中的成员变量(属性)
		//System.out.println("车牌号:"+id+"\n颜色:"+color+"\n价格:"+price);
		//上一条语句可以编写为如下:
		System.out.println("车牌号:"+this.id+"\n颜色:"+this.color+"\n价格:"+this.price);
	}
	public void print2(String id){//id是形参,属于局部变量
		System.out.println("输出成员变量id:"+this.id);
	}
	public void print3(){
		//调用本类中的print方法,可以直接使用:方法名称([参数列表]);
		print();//等价于this.print()
	}
}

//编写测试类
class CarTest{
	public static void main(String[] args){
		//实例化车
		Car c = new Car();
		c.print();
		//System.out.println(this.id);//编译错误,因为this只能在本类(当前类)中使用
		
		Car car = new Car();
		car.print();//this就是car即当前调用这个方法的对象
		
		Car c3 = new Car();
		c3.print3();
		
		//创建对象同时执行带两个参数的构造方法
		Car c4 = new Car("京A88888",800000);
		c4.print();
		
		Car c5 = new Car("沪C55555","黄色",5000000);
		c5.print();
	}
}

Day09

9.1参数传递

基本数据类型作为参数传递

传递的是真正的值,在一个方法中改变本类的值,对另一个方法中变量的值没有任何影响,各自变量是独立的

class Method01{
	public static void swap(double a,double b){
		double t = a;
		a = b;
		b = t;
		System.out.println(a);
		System.out.println(b);
	}
	public static void change(int x,int y){
		x += 5;
		y += 10;
		System.out.println("x="+x);
		System.out.println("y="+y);
	}
	public static void main(String[] args){
		int x = 10,y = 20;
		System.out.println("x:"+x);//x:10
		System.out.println("y:"+y);//y:20
		change(x,y);//x=15  y=30.弹栈了,xy不在了
		System.out.println("x的值:"+x);//x的值:10
		System.out.println("y的值:"+y);//y的值:20
		
		double num1 = 3.4,num2 = 10.6;
		swap(num1,num2);//10.6  3.4
		//System.out.println(a);//报错
		System.out.println(num1);//3.4
		System.out.println(num2);//10.6
	}
}

引用数据类型作为参数传递

传递的是地址,也就是说多个引用名称共用一个对象

class Student{
	//属性
	String name;
	int age;
	//构造方法
	public Student(){
		
	}
	public Student(String name,int age){
		this.name = name;
		this.age = age;
	}
}
//编写学生测试类
class StudentTest{
	public static void main(String[] args){
		//实例化学生
		Student s = new Student("张三",19);
		Student s2;//在main方法中声明,局部变量
		s2 = s;//s和s2共用同一个地址,也就是说s和s2引用名称指向一个对象
		System.out.println("s2.name="+s2.name);//s2.name=张三
		System.out.println("s2.age = "+s2.age);//s2.age = 19
		s2.name = "李四";
		System.out.println("s2.name = "+s2.name);//李四
		System.out.println("s.name = "+s2.name);//李四
	}
}

Java-面向对象_第6张图片

class Student{
	//属性
	String name;
	int age;
	//构造方法
	public Student(){
		
	}
	public Student(String name,int age){
		this.name = name;
		this.age = age;
	}
}
//编写学生测试类
class StudentTest{
	public static void change(Student s){
		System.out.println(s.name);
		System.out.println(s.age);
		s.name = "无名氏";
	}
	public static void main(String[] args){
		Student s = new Student("李四",23);
		System.out.println(s.name);//李四
		System.out.println(s.age);//23
		change(s);
		System.out.println(s.name);//无名氏
	}
}

9.2static关键字

  • static关键字可以修饰属性
    • 称为静态属性也叫类的变量
    • 在方法区(共享区)中存储,并且所有对象都能访问
    • 与类同生死,也就是说类在static修饰的属性就存在
    • 可以使用类名.属性名称,也可以使用引用名称.属性名称
      注意:引用名称的值为null时,也可以访问静态属性,不会出现空指针异常
    • 类优先于对象,也就是说类的生命周期比较长
/*
 * 编写学生类,属性:名字、现住址(北京)
 * */
class Student1{
	//构造方法
	public Student1(){
		
	}
	public Student1(String name){
		this.name = name;
		
	}
	//属性
	String name;//称为非静态属性,也叫做实例变量
	static String address = "北京";//称为静态属性也叫类的变量
}
//编写学生测试类
class Student1Test{
	public static void main(String[] args){
		//创建对象
		Student1 s= new Student1();
		Student1 s2 = new Student1("张三");
		System.out.println(Student1.address);//静态属性与类同生死 
		System.out.println(s.name);
		System.out.println(s.address); 
	}
}

Java-面向对象_第7张图片

  • static关键字可以修饰方法
    • 称为静态方法也叫类的方法
    • 与类同生死,也就是说类在static修饰的方法就存在
    • 可以使用类名.方法名称([参数列表]);也可以使用引用名称.方法名称([参数列表]);
      注意:引用名称的值为null时,也可以访问静态方法,不会出现空指针异常
    • 静态方法中只能访问静态属性、静态方法
    • 当方法体中只访问静态属性、静态方法时,可以编写为静态方法
  • static关键字可以修饰代码块
    • 主要完成对静态属性赋值
    • 静态代码块在类第一次被载入时则执行
class Student1{
	//构造方法
	public Student1(){
		
	}
	public Student1(String name){
		this.name = name;
		
	}
	//属性
	String name;
	static String address = "北京";
	
	//称为静态方法也叫类的方法
	public static void print2(){
		
	}
	public static void print(){
		System.out.println("执行了print方法");
		//System.out.println(name);//静态方法中只能访问静态属性、静态方法
		System.out.println(address);
		print2();
	}
	//称为非静态方法也叫实例方法
	public void show(){
		System.out.println("执行了show方法");
	}
}
//编写学生测试类
class Student1Test{
	public static void main(String[] args){
		
		Student1.print();//执行了print方法
		Student1 s1 = new Student1();
		System.out.println(s1.name);//null
		s1.show();//执行了show方法 
		s1.print();//执行了print方法
		s1 = null;
		//s1.show();//出现运行错误,因为对象不存在
		s1.print();//执行了print方法
	}
}

9.3什么是继承

编写狗类,属性:名字、年龄、品种、颜色,方法:显示信息
编写猫类,属性:名字、颜色、性别、年龄,方法:显示信息
编写测试类,创建猫和狗的对象,并分别显示信息

分析得到:
如果多个类中有相同属性和方法,能否单独编写一个类?----》能
解决办法:

  • 1.将多个类中相同的属性和方法编写在单独一个类中,该类称为父类
  • 2.然后再子类继承父类,然后再子类中编写独有的属性和方法

动物类:
  属性:名字、年龄、颜色
  方法:显示信息
    狗类,继承,动物类
      独有属性:品种
    猫类,继承,动物类
      独有属性:性别

9.4继承好处

减少代码的冗余性

9.5编写继承代码步骤

  • 第一步:编写父类
[修饰符] class 类名{
	//属性和方法
}
  • 第二步:编写子类
[修饰符] class 子类类名 extends 父类类名{
	//编写独有属性和方法
}

注意:

  1. 当一个类没有指明继承具体哪个父类时则默认继承object类
  2. object类是所有类的父类(超类)
class Animal{
	//属性
	String name;
	int age;
	String color;
	//方法:显示信息
	public void show(){
		System.out.println("名字:"+name+"\n年龄:"+age+"\n颜色:"+color);
	}
}
//编写狗的子类继承动物父类
class Dog extends Animal{
	//编写子类中独有属性和方法
	String strain;
	
}
//编写猫的子类并继承动物父类
class Cat extends Animal{
	//编写子类中独有属性:性别
	char sex;
}

9.6 继承中注意事项

  • 子类继承父类,但是不能继承父类的构造方法
  • 父类也叫超类(基类),子类也叫派生类
  • 继承满足的条件:
    • is a 如:猫 是 动物
  • 继承具有两大特性:
    • 一个类只能继承一个直接的父类,也就是说类是单根性
    • 类具有传递性
class A {
	//编写2个属性2个方法
}
class B extends A{
	//独有属性1个,方法3个 # B里3个属性5个方法
}
class C extends A{
	//编写独有属性1
}
class D extends B{
	# D继承B里3个属性5个方法
}

9.7 重写

override也叫做覆盖

  • 子类方法名称必须与父类方法名称一致
  • 参数列表一致
  • 返回类型一致或父类方法返回类型的子类类型
  • 修饰符不能缩小范围
    子类不能重写:
  • 构造方法不能重写
  • 属性不能重写
  • 静态方法不能重写
  • 私有方法不能重写
class Animal{
	//属性
	String name;
	int age;
	String color;
	//方法:显示信息
	public void show(){
		System.out.println("名字:"+name+"\n年龄:"+age+"\n颜色:"+color);
	}
	public Object getInfo(){
		return null;
	}
}
//编写狗的子类继承动物父类
class Dog extends Animal{
	//编写子类中独有属性和方法
	String strain;
	//重写也叫覆盖override:在子类中重写父类的方法,必须与父类的方法名称一致、参数列表一致、返回类型一致、修饰符一致
	public void show(){
		//在子类中可以直接访问父类中的属性(前提:父类中属性没有使用private修饰)
		System.out.println("名字:"+name+"\n年龄:"+age+"\n颜色:"+color+"\n品种:"+strain);
	}
	//重写父类的getInfo方法
	public String getInfo(){
		return "OK";
	}
}
//编写猫的子类并继承动物父类
class Cat extends Animal{
	//编写子类中独有属性:性别
	char sex;
}
//编写测试类
class Test{
	public static void main(String[] args){
		//创建狗的对象
		Dog d = new Dog();
		//显示信息
		d.show();//先在Dog类中找show方法,如果没有找到则到父类中找
	}
}

你可能感兴趣的:(Java-面向对象)