1.继承
- 继承概述
继承是面向对象三大特征之一。可以使得子类具有父类的属性和方法,还可以在子类中重新定义,追加属性和方法
- 继承的格式
//格式:
public class 子类名 extends 父类名{}
//范例
public class Zi extends Fu{}
//FU:是父类,也被称为基类,超类
//Zi:是子类,也被称为派生类
//父类
public class Fu {
public void show(){
System.out.println("show方法被调用");
}
}
//子类
public class Zi extends Fu{
public static void method(){
System.out.println("method方法被调用");
}
}
//测试类
public class Demo {
/*测试类*/
public class Demo {
/*测试类*/
public static void main(String[] args) {
Fu f = new Fu();
f.show();//结果: show方法被调用
Zi z = new Zi();
z.method();//结果: method方法被调用
z.show();//结果: show方法被调用
}
}
- 继承中子类的特点
①:子类可以有父类的内容
②:子类还可以有自己特有的内容
2.继承的好处和弊端
- 继承的好处
①:提高了代码的复用性(多个类相同的成员可以放到同一个类中)
②:提高了代码的维护性(如果方法的代码需要修改,修改一处即可)
- 继承的弊端
①:继承让类与类之间产生了关系,类的耦合性增强了,当父类发送变化时子类实现也不得不跟着变化,削弱了子类的独立性
- 什么时候使用继承
①:继承体现的关系:is a
②:假设法:我有两个类A和B,如果他们满足A是B的一种,或者B是A的一种,就说明他们之间存在继承关系,这个时候可以考虑使用继承来体现,否则就不能使用继承。
③:举例
苹果和水果:苹果是水果的一种,因此可以设水果为父类,苹果为子类。
猫和动物:猫是动物的一种,因此可以设动物是父类,猫是子类。
猫和狗:猫不是狗,狗不是猫,因此不能用继承
3.继承中变量的访问特点
在一个子类中访问一个变量(按顺序①-③顺序执行)
①:在子类局部范围找。
②:子类成员范围找
③:父类成员范围找
注:如果都没有就报错(不考虑父亲的父亲……)
4. super
- super关键字的用法和this关键字用法相似
①:this:代表本类对象的使用
②:super:代表父类存储空间的标识(可以理解为父类对象引用)
关键字 | 访问成员变量 | 访问构造 | 访问成员方法 |
---|---|---|---|
this | this.成员:变量访问本类 | this(……):访问本类构造方法 | this.成员方法(……):访问本类成员方法 |
super | super.成员变量:访问父类成员变量 | super(……):访问父类构造方法 | super.成员变量(……):访问父类成员方法 |
//父类
public class Fu {
public int age =40;
}
//子类
public class Zi extends Fu{
public int age = 20;
public void show(){
int age = 30;
System.out.println("show方法中的变量age:"+age);
//需求:访问本类的成员变量age,怎么搞?
System.out.println("子类中的成员变量age:"+this.age);
//需求:访问父类的成员变量age,怎么搞?
System.out.println("父类中的成员变量age:"+super.age);
}
}
//测试类
public class Demo {
/*测试类*/
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
5.继承中构造方法的访问特点
- 子类中所有的构造方法默认都会访问父类中无参构造方法
原因:①、因为子类会继承父类中的数据,可能还会使用父类的数据。因此,子类初始化之前,一定要先完成父类数据的初始化。
②、每一个子类构造方法的第一条语句默认都是super
//父类
public class Fu {
public Fu(){
System.out.println("调用父类中无参构造方法");
}
public Fu(int age){
System.out.println("调用父类中带参构造方法");
}
}
//子类
public class Zi extends Fu{
public Zi(){
// super();
System.out.println("调用子类中无参构造方法");
}
public Zi(int age){
// super();
System.out.println("调用子类中带参构造方法");
}
}
//测试类
public class Demo {
/*测试类*/
public static void main(String[] args) {
/*Zi z = new Zi();
*//*结果:
调用父类中无参构造方法
调用子类中无参构造方法*/
Zi z2 =new Zi(12);
/*结果:
调用父类中无参构造方法
调用子类中带参构造方法*/
// 解释: 子类中所有的构造方法默认都会访问父类中无参构造方法
}
}
- 如果父类中没有无参构造方法,只有有参构造方法,该怎么办呢?
①:通过使用super关键字去显示的调用父类中的带参构造方法
②:在父类中自己提供一个无参构造方法
推进:自己给出无参构造方法
//父类
public class Fu {
/* public Fu(){
System.out.println("调用父类中无参构造方法");
}*/
public Fu(int age){
System.out.println("调用父类中带参构造方法");
}
}
//子类
public class Zi extends Fu{
public Zi(){
super(20);
System.out.println("调用子类中无参构造方法");
}
public Zi(int age){
super(20);
System.out.println("调用子类中带参构造方法");
}
}
//测试类
public class Demo {
/*测试类*/
public static void main(String[] args) {
Zi z2 =new Zi(12);
/*结果:
调用父类中带参构造方法
调用子类中带参构造方法*/
}
}
6. 继承中成员变量的访问特点
- 通过子类对象访问一个 方法
①:子类成语范围找
②:父类成员范围找
③:如果都没有就报错(不考虑父亲的父亲……)
//父类
public class Fu {
public void show(){
System.out.println("父类中得到show方法被调用");
}
}
//子类
public class Zi extends Fu{
public void method(){
System.out.println("子类中的method方法被调用");
}
public void show(){
super.show();
System.out.println("子类中得到show方法被调用");
}
}
//测试类
public class Demo {
/*测试类*/
public static void main(String[] args) {
Zi z =new Zi();
z.method();
z.show();
/*结果:
子类中的method方法被调用
父类中得到show方法被调用
子类中得到show方法被调用*/
/*z.text();
//报错*/
}
}
7.方法重写
- 方法重写
①子类中出现了和父类中一模一样的方法声明
- 方法重写的应用
①当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,既沿袭了父类的功能,又定义了子类特有的内容。
- 练习:手机类和新手机类
//phone类
package phone;
//手机类
public class phone {
public void cell(String name){
System.out.println("给"+name+"打电话");
}
}
//newPhone 类
package phone;
//新手机
public class newPhone extends phone{
/*public void cell(String name){
System.out.println("给"+name+"开视频");
// System.out.println("给"+name+"打电话");
super.cell(name);
}*/
@Override//一个帮助检查方法重写时方法名是否错误
public void cell(String name){
System.out.println("给"+name+"开视频");
// System.out.println("给"+name+"打电话");
super.cell(name);
}
}
//PhoneDemo测试类
package phone;
//测试类
public class PhoneDemo {
public static void main(String[] args) {
//创建对象,调用方法
phone p = new phone();
p.cell("王冰冰");
System.out.println("----------");
newPhone np = new newPhone();
np.cell("王冰冰");
}
}
8.方法重写的注意事项
- 私有方法不能被重写(父类私有成员子类不能继承的)
- 子类的访问权限不能更低(public>默认>私有)
//父类
package test;
public class Fu {
private void show(){
System.out.println("父类中的show方法被调用");
}
/* public void method(){
System.out.println("父类中的method方法被调用");
}*/
void method(){
System.out.println("父类中的method方法被调用");
}
}
//子类
package test;
public class Zi extends Fu{
/* @Override
public void show(){
System.out.println("子类中的show方法被调用");
}*/
/* @Override
public void method(){
System.out.println("子类中的method方法被调用");
}*/
void method(){
System.out.println("子类中的method方法被调用");
}//有错,子类重写父类方法,其
}
9. Java中继承的注意事项
- Java中类只支持单继承,不支持多继承
- Java中类支持多层继承(儿子继承父亲,父亲继承爷爷===这样就形成了多层继承体系)
//Grandfather
package family;
public class Grandfather {
public void Smoking(){
System.out.println("爷爷爱抽烟");
}
}
//father
package family;
public class father extends Grandfather{
public void Drinking(){
System.out.println("爸爸爱喝酒");
}
}
//mother
package family;
public class mother {
public void hotHead(){
System.out.println("妈妈爱烫头");
}
}
//son
package family;
/*public class son extends father,mother{
//报错,java中不能同时继承多个类
}*/
public class son extends father{
}
1. 案例:老师和学生
需求:定义老师类和学生类,然后写代码测试;最后找到老师类和学生类当中的共同内容,抽取出一个父类,用继承的方式写代码,并进行测试。
//父类
package Case;
public class human {
private String name;
private int age;
//无参构造方法
public human(){
}
//有参构造方法
public human(String name,int age){
this.age = age;
this.name = name;
}
//get方法
public String getName(){
return name;
}
public int getAge(){
return age;
}
//set方法
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
}
//学生子类
package Case;
//学生类
public class Student extends human{
/* private String name;
private int age;
//无参构造方法
public Student(){
}
//有参构造方法
public Student(String name,int age){
this.name = name;
this.age = age;
}
//get方法
public String getName(){
return name;
}
public int getAge(){
return age;
}
//set方法
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}*/
public Student(){}
public Student(String name,int age){
super(name, age);
}
//study方法
public void study(){
System.out.println("努力学习");
}
}
//老师子类
package Case;
//老师类
public class Teacher extends human{
/*private String name;
private int age;
//无参构造方法
public Teacher(){
}
//有参构造方法
public Teacher(String name,int age){
this.age = age;
this.name = name;
}
//get方法
public String getName(){
return name;
}
public int getAge(){
return age;
}
//set方法
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}*/
public Teacher(){}
public Teacher(String name,int age){
super(name,age);//把name,age传给父类的带参构造方法为name,age赋值
}
//teach方法
public void teach(){
System.out.println("努力教书");
}
}
//测试类
package Case;
//测试类
public class Demo {
public static void main(String[] args) {
//创建老师类对象进行测试
//无参构造
Teacher t = new Teacher();
t.setAge(19);
t.setName("明明");
System.out.println(t.getName());
System.out.println(t.getAge());
t.teach();
System.out.println("============");
//带参构造
Teacher t1 = new Teacher("明磊",19);
System.out.println(t1.getName());
System.out.println(t1.getAge());
t1.teach();
System.out.println("============");
//创建学生类对象进行测试
//无参构造
Student s = new Student();
s.setAge(20);
s.setName("张三");
System.out.println(s.getName());
System.out.println(s.getAge());
s.study();
System.out.println("============");
//带参构造
Student s1 = new Student("李四",30);
System.out.println(s1.getName());
System.out.println(s1.getAge());
s1.study();
System.out.println("============");
}
}
2.案例:猫和狗
需求:请采用继承的思想实现猫和狗的案例,并在测试类中进行测试。
分析:
- 猫:①、成员变量:姓名,年龄
②、构造方法:无参,带参
③、成员方法:get/set方法,抓老鼠()
- 狗:①、成员变量:姓名,年龄
②、构造方法:无参,带参
③、成员方法:get/set方法,多管闲事()
//父类
package DogAndCat;
public class Fu {
private String name;
private int age;
//无参构造方法
public Fu(){}
//带参构造方法
public Fu(String name,int age){
this.age = age;
this.name = name;
}
//get方法
public String getName(){
return name;
}
public int getAge(){
return age;
}
//set方法
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
}
//子类狗
package DogAndCat;
public class Dog extends Fu{
//构造方法
public Dog(){}
public Dog(String name,int age){
super(name, age);
}
//多管闲事成员方法
public void dogs(){
System.out.println("多管闲事");
}
}
//子类猫
package DogAndCat;
public class Cat extends Fu{
//构造方法
public Cat(){}
public Cat(String name,int age){
super(name, age);
}
//成员方法抓老鼠
public void Grasp(){
System.out.println("抓老鼠");
}
}
//测试类
package DogAndCat;
public class Demo {
public static void main(String[] args) {
//创建狗类对象====无参构造
Dog d = new Dog();
d.setAge(10);
d.setName("菅义伟");
System.out.println(d.getName()+","+d.getAge());
d.dogs();
System.out.println("============");
//创建狗类对象====无参构造
Dog d1 = new Dog("安倍晋三",11);
System.out.println(d1.getName()+","+d1.getAge());
d1.dogs();
System.out.println("============");
//创建猫类对象=====无参构造
Cat c = new Cat();
c.setAge(10);
c.setName("黑猫警长");
System.out.println(c.getName()+","+c.getAge());
c.Grasp();
System.out.println("============");
//创建狗类对象====无参构造
Cat c1 = new Cat("加菲猫",11);
System.out.println(c1.getName()+","+c1.getAge());
c1.Grasp();
System.out.println("============");
}
}
10.修饰符
1.包
其实就是文件夹
作用就是对类进行分类管理
包的定义格式:①格式:package 包名;(多级包用.分开)
②范例:package com. ming;
带包的Java类编译和执行
- 手动建包
①:按照以前的格式编译Java文件— java HelloWorld .java
②:手动创建包------在E盘建立文件夹com,然后com下建立文件夹mingming
③:把class文件放到包的最里面-----把HelloWorld.class文件放到com下的mingming文件夹下
④:带包执行:java com.mingming.HelloWorld
- 自动建包
编译时:java -d . HelloWorld.java
执行:java com . mingming.HelloWorld
2.导包
使用不同包下的类时,使用的时候要写类的全路径,写起来太麻烦了。为了简化带包的操作,Java就提供了导包的功能。
导包的格式:
①格式:import 包名;
②范例:import tset1.case1;
//包1中的类
package tset1;
public class case1 {
public void mm(){
System.out.println("测试");
}
}
//包2中的类
package tset2;
import tset1.case1;//导包
public class case2 {
public static void main(String[] args) {
// tset1.case1 c1 = new tset1.case1();//不导包的情况下
case1 c = new case1();
c.mm();
}
}
3.权限修饰符
修饰符 | 同一个类 | 同一个包中的子类和无关类 | 不同包的子类 | 不同包的无关类 |
---|---|---|---|---|
private | ✔ | |||
默认 | ✔ | ✔ | ||
protected | ✔ | ✔ | ✔ | |
public | ✔ | ✔ | ✔ | ✔ |
4. final修饰局部变量
①、变量是基本类型:final修饰指的是基本类型的数据值不能发生改变。
②、变量是引用类型:final修饰指的是引用类型的地址值不能发生改变,但是地址里面的内容是可以发生改变的。
5. static关键字
static关键字是静态的意思,可以修饰成员方法,成员变量。
- static修饰的特点
①、被类的所有对象共享
这也是判断是否使用静态关键字的条件
②、可以使用类名调用,也可以通过对象名调用(推荐使用类名调用)
//student类
package study_day01;
public class student {
public String name;//姓名
public int age;//年龄
// public String university;//学校
public static String university;//学校
public void show(){
System.out.println(name+","+age+","+university);
}
}
//studentDemo
package study_day01;
public class studentDemo {
public static void main(String[] args) {
student.university = "国防科大";//建议这样写
student st = new student();
st.name ="明明";
st.age = 19;
// st.university = "国防科大";//不建议这样写
st.show();
student st1 = new student();
st1.name ="帅帅";
st1.age = 19;
// st1.university = "国防科大";
st1.show();
}
}
6. static访问特点
- 非静态的成员方法
①、能访问静态的成员变量
②、能访问非静态的成员方法
③、能访问静态的成员方法
④、能访问非静态的成员方法
- 静态成员方法
①、能访问静态的成员变量
②、能访问静态的成员方法
package study_day01_1;
public class student {
//非静态成员变量
private String name = "明明";
//静态成员变量
private static int age = 19;
//非静态成员方法
private void show1(){
}
//非静态成员方法
private void show2(){
System.out.println(name);
System.out.println(age);
show1();
show3();
}
//静态成员方法
private static void show3(){
}
//静态成员方法
private static void show4(){
// System.out.println(name);//报错
System.out.println(age);
// show1();//报错
show3();
}
}
总结:静态成员方法只能访问静态成员