什么是继承?
- 一种类与类之间的关系
- 使用已存在的类定义作为基础建立的类
- 新类的定义可以增加新的数据或新的功能,也可以用父类大的功能,但不能选择性的继承父类。
继承的关系:
·满足“A is a B”的关系就可以形成继承关系。(猫和狗都是动物)
继承的实现
- 子类可以访问父类的非私有成员、子类之间也是无法进行访问的。
- 父类无法访问子类的特有成员、哪怕是公有的。
方法的重写
重载和重写的区别?
方法重载:
1、是在同一个类当中的的
2、方法名相同、参数列表不同(参数个数、数据类型、顺序)
3、方法返回值,访问修饰符任意
4、与方法名参数无关
方法重写:
1、有继承关系的子类中(子类重写父类的方法)
2、方法名相同、参数列表相同(参数个数、参数顺序、参数类型)
3、访问修饰符可以修改,但是必须大于等于父类修饰符的作用范围
4、与方法的参数名无关,返回值运行是子类类型
5、子类调用自己重写父类的方法、不再调用父类的这个方法(子类中,可以定义与父类重名的属性)
关于父类静态方法不能被子类重写?
原因:静态方法是类在加载时就被加载到内存中的方法,在整个运行过程中保持不变,因而不能重写。
但非静态方法是在对象实例化时才单独申请内存空间,为每一个实例分配独立的运行内存,因而可以重写
父类的构造,不允许被继承、不允许被重写。
子类继承的初始化:
继承案例:
工作:Work.java
测试工作:Test.java
研发工作:DevelopmentWork.java
子类共有属性:工作名称(workName)
Work.java
package com.demo.day5.extend;
import java.util.Scanner;
/**
* 这是工作的父类,存放工作的共有属性
* @author Mr-Donkey
*
*/
public class Work {
private String workName;//工作名称
public static String input;//输入内容
//无参的构造函数
public Work() {
System.out.println("请输入内容:");
//从键盘输入数据
Scanner sc=new Scanner(System.in);
input=sc.next();
this.setWorkName(workName);
}
public String getWorkName() {
return workName;
}
public void setWorkName(String workName) {
this.workName = workName;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
TestWork.java
package com.demo.day5.extend;
/**
* 这是测试工作的类、定义编写用例测试个数、发现Bug的个数
* @author Mr-Donkey
*
*/
//继承工作Work.java
public class TestWork extends Work {
private String testNum;//测试用例个数
private int bugNum;//发现bug个数
//无参构造函数
public TestWork() {
this.setBugNum(bugNum);
this.setTestNum(testNum);
}
public String getTestNum() {
return testNum;
}
public void setTestNum(String testNum) {
this.testNum = testNum;
}
public int getBugNum() {
return bugNum;
}
public void setBugNum(int bugNum) {
this.bugNum = bugNum;
}
//显示的方法
public String showTestWorkInfo() {
String info=this.getWorkName()+"的日报是:"+"今天编写了"+this.getTestNum()+"个测试用例"+" 发现了"+this.getBugNum()+"个Bug";
return info;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
DevelopmentWork.java
package com.demo.day5.extend;
/**
* 这是研发工作类、主要定义有效编码行数、目前未解决的bug
* @author Mr-Donkey
*
*/
//继承工作父类
public class DevelopmentWork extends Work{
private int codeNum;
private int bugNum;
//无参构造函数
public DevelopmentWork() {
this.setBugNum(bugNum);
this.setCodeNum(codeNum);
}
public int getCodeNum() {
return codeNum;
}
public void setCodeNum(int codeNum) {
this.codeNum = codeNum;
}
public int getBugNum() {
return bugNum;
}
public void setBugNum(int bugNum) {
this.bugNum = bugNum;
}
//显示信息的方法
public String showDevelopmentWorkInfo() {
String arr=this.getWorkName()+"日报是:"+"今天编写了"+this.getCodeNum()+"行代码"+" 目前仍有"+this.getBugNum()+"个bug没解决";
return arr;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
Test.java
package com.demo.day5.test;
import com.demo.day5.extend.*;
/**
* 测试方法
* @author Mr-Donkey
*
*/
public class Test {
public Test() {
}
public static void main(String[] args) {
// TODO Auto-generated method stub
//测试工作的实例化对象
TestWork test=new TestWork();
test.setWorkName("测试工作");
test.setTestNum("10");
test.setBugNum(5);
System.out.println(Work.input);//静态类属性(test.input)
System.out.println(test.showTestWorkInfo());
//研发工作的实例化对象
DevelopmentWork dl=new DevelopmentWork();
dl.setWorkName("研发工作");
dl.setCodeNum(1000);
dl.setBugNum(10);
System.out.println(dl.showDevelopmentWorkInfo());
}
}
结果:
请输入内容:
1
1
测试工作的日报是:今天编写了10个测试用例 发现了5个Bug
请输入内容:
1
研发工作日报是:今天编写了1000行代码 目前仍有10个bug没解决
访问修饰符(属性)
作用范围:
private:只允许在本类中进行访问
public:允许在任意位置访问
protect:允许在当前类、同包子类/非子类、跨包子类调用、跨包非子类不允许
默认:允许在当前类、同包子类/非子类调用、跨包子类/非子类不允许调用
Super 关键字
是父类对象的引用。
在子类重写父类的方法时,由于子类父类都存在一个方法,它会只执行子类中的这个方法,那么我们要执行父类的方法的时候怎么办?
super.父类方法();//这时候就是调用了父类的方法了。
子类构造默认调用父类的无参构造方法,可以通过super();调用父类允许被访问的其他构造方法;
如果要调用的父类构造方法,有参数,子类直接将参数super(参数);进行说明我调用的是父类这个有参的构造方法!
注意:这个super(); 必须放在子类有效构造方法的第一行(构造方法调用构造方法 )。
使用super关键字的注意事项:
this和super的区别
this:当前访问对象(同一个类)
super:父类的引用对象
两个都不能在静态方法中使用,不能同时存在一个方法里,因为两者都要抢占第一行的位置(一山不容二虎)
Object类
equals测试:继承Object中的equals方法时,比较的是两个引用是否指向同一个对象
//子类可以通过重写equals方法来进行值的判断
Animal one=new Animal("123",1);
Animal two=new Animal("123",2);
boolean flag=one.equals(two);
System.out.println("one和two的引用比较:"+flag);
System.out.println("one和two的引用比较:"+(one==two));
//String 这个类重写了equals方法
String str1=new String("hello");
String str2=new String("hello");
boolean flag=str1.equals(str2);
System.out.println("str1和str2的引用比较:"+flag);
System.out.println("one和two的引用比较:"+(str1==str2));
one和two的引用比较:false
one和two的引用比较:false
//String 的equals方法时比较里面数值
str1和str2的引用比较:true
str1和str2的引用比较:false
toString方法测试:继承Object中的toString方法时,输出对象的字符串表示形式:类型信息+@+地址信息
//子类可以通过重写toString方法的形式,改变输出的内容以及表现形式
final关键字
Java关键字final有“这是无法改变的”或者“终态的”含义,它可以修饰非抽象类、非抽象类成员方法和变量。
-
final类不能被继承,没有子类,final类中的方法默认是final的。
-
final方法不能被子类的方法覆盖,但可以被继承。
-
final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
-
final不能用于修饰构造方法。
注意:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。
1、final类
final类不能被继承,因此final类的成员方法没有机会被覆盖,默认都是final的。在设计类时候,如果这个类不需要有子类,类的实现细节不允许改变,并且确信这个类不会载被扩展,那么就设计为final类。
2、final方法
如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。使用final方法的原因有二:
①把方法锁定,防止任何继承类修改它的意义和实现。
②高效,编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。
final class:该类没有子类 可以写成public final class\final public class
final 方法:该方法不允许被子类重写,但是可以正常被子类继承使用
final 方法内部变量:只要在具体被使用之前进行复制即可,一旦被赋值,不允许被修改
类中成员属性:赋值过程:1、定义直接初始化 2、构造方法中初始化 3构造代码块中
static和final一起使用
- static final用来修饰成员变量和成员方法,可以理解为“全局变量”
- 对于变量,表示一旦给值就不可修改,并且通过类名可以访问。
- 对于方法,表示不可覆盖,并且可以通过类名直接访问。
static:
static可以修饰:属性,方法,代码段,内部类(静态内部类或嵌套内部类)
static修饰的属性的初始化在编译期(类加载的时候),初始化后能改变。
static修饰的属性所有对象都只有一个值。
static修饰的属性强调它们只有一个。
static修饰的属性、方法、代码段跟该类的具体对象无关,不创建对象也能调用static修饰的属性、方法等
static和“this、super”势不两立,static跟具体对象无关,而this、super正好跟具体对象有关。
static不可以修饰局部变量。
static final和final static:
static final和final static没什么区别,一般static写在前面。
注意:
对于被static和final修饰过的实例常量,实例本身不能再改变了,但对于一些容器类型(比如,ArrayList、HashMap)的实例变量,不可以改变容器变量本身,但可以修改容器中存放的对象。
总结: