什么是继承
继承的本质就是代码的复用,是子类重复使用父类的代码,父类是无法使用子类的代码的
测试类
public class Test {
public static void main(String[] args) {
//继承的本质就是代码的复用,是子类重复使用父类的代码,父类是无法使用子类的代码的
Student student=new Student();
student.study();//子类可以有自己的方法
student.a();
student.height=180.0;
Person person=new Person();
}
}
子类
public class Student extends Person{
public void study(){
System.out.println("好好学习");
}
}
父类
public class Person {
public double height;
public String name;
public char sex;
public void run(){
System.out.println("可以跑");
}
public void a(){
System.out.println("可以跳");
}
}
父类不可以调用子类的方法
继承层次
java支持单继承
java的继承层次当中是不能互相继承的(示例中,Student已经继承Person)
一个父类可以有多个子类,一个子类只能有一个父类
方法重写和方法重载的区别
1.java的修饰符
public:共有
a.在本类可以访问到
b.在子类可以访问到
c.同包可以访问到
d.不同包可以访问到
private:私有
a.在本类可以访问到
b.在子类无法访问
c.同包无法访问到
d.不同包无法访问到
protected:受保护的
a.在本类可以访问到
b.在子类可以访问到
c.同包可以访问到
d.不同包无法访问到
不写
a.在本类可以访问到
b.在子类可以访问到
子类不同包也是不可以访问的
d.同包可以访问到
e.不同包无法访问到
小结
public修饰的代码,本类其他类都是可以访问的
private修饰的代码,本类是可以访问的,但是其他类是不可以访问的
2.普通方法
1.方法是有访问权限的
2.方法必须写上返回数据的类型(return+返回值),如果不需要返回数据,就需要写void(可以只写return,也可以不写,不需要返回值)
void study(){
System.out.println("好好学习");
age();
return;
}
private int age(){
return 18;
}
3.在同一个类当中,方法名可以相同,但方法的签名不能相同 方法的签名:方法名+参数列表的类型
void study(int age){
System.out.println("好好学习");
}
void study(String name){
System.out.println("好好学习");
}
void study(String name,int age){//返回参数列表
System.out.println("好好学习");
}//此时不报错
必须参数类型不同
4.方法上可以使用其他关键字进行修饰,比如static和final 有不同的意义
3.构造器:又叫构造方法和构造函数
创建对象的时候,给对象赋初始值的
package Work;
public class A {
//1.在类当中构造函数必须和类名相同
//2.在类当中,有一个默认的,不显示的,无参数的构造器,一旦在类当中写一个构造器,Negev无参的构造器就会被覆盖
//3.构造器是不需要写返回类型的
//4.一个类当中可以有多个构造函数
//在创建对象的时候,给对象的变量赋初始值
private String name;
private int age;
private char sex;
private int sno;
public A(String name){
this.name=name;
}
}
1.在类当中构造函数必须和类名相同
2.在类当中,有一个默认的,不显示的,无参数的构造器,一旦在类当中写一个构造器,那个无参的构造器就会被覆盖
3.构造器是不需要写返回类型的
4.一个类当中可以有多个构造函数
例1
package Work;
public class A {
private String name;
private int age;
private char sex;
private int sno;
public A(String name){
this.name=name;
}
public A(String name,int age){
this.name=name;
this.age=age;
}
}
package Work;
public class B {
public static void main(String[] args) {
A a=new A("张三");
}
}
A a=new A("张三")代码执行过程
1.开辟新内存空间:
2.在内存空间中创建变量
一开始创建的对象的name值为空
3.public A(String name){
this.name=name;
}由于调用了这个构造函数,会给对象中的name赋值“张三”
构造器会给创建的变量赋值
4.方法的重载和重写
方法的重载:
发生在本类当中,方法名相同,但是参数列表不同,就是方法的重载
package Work;
public class A {
//方法的重载:在同一个类当中,方法名相同,但是参数列表不同,就是方法的重载
public void study(){
}
public void study(String name){
}
}
注:
方法只有在方法中才能调用出来
java的执行流程是方法的入栈出栈
main方法会自动入栈
一个方法的入栈只有在另一个方法调用时
每个方法都有不同的功能
方法的重写:
发生在父子类当中,子类重新实现父类方法的功能
为什么会发生重写?
继承的本质是代码的复用,在复用的过程当中,父类方法的实现不一定适用子类,这恶时候就涉及到方法的重写,
package Work;
public class A {
public void study(String name){
String a="123";
}
public void run(){
System.out.println("A跑起来");
}
}
B继承A,并重写run方法
package Work;
public class B extends A {
public void run(){
System.out.println("B跑起来");
}
}
测试类
package Work;
public class Test {
public static void main(String[] args) {
B b=new B();
b.run();
}
}
方法的重写之后,子类对象调用的也是重写之后的方法
例2 !!!
package work2;
/*
*程序执行的流程 找main()方法启动程序
* 1.首先先去扫描Base类,发现Base类没有父类
* 2.将Base.class加载到内存的方法区,此时Base类当中的static方法执行
* 3.再去扫描Test类,发现其父类Base已经加载到内存中
* 3.将Test.class加载到内存的方法区,此时Test类当中的static方法执行
* 4.main方法入栈--------->执行 new Test() 去创建Test类的对象
* 5.创建子类对象之前先创建父类对象,所以先执行Base()构造器,再执行Test()构造器
* */
public class Test extends Base {
static{
System.out.println("test static");
}
public Test(){
System.out.println("test constructor");
}
}
class Base{
static{
System.out.println("base static");
}
public Base(){
System.out.println("base constructor");
}
public static void main(String[] args) {
new Test();
}
}
{}代码块:static修饰的代码块在main方法之前执行,其目的是修饰main方法
程序执行流程
先扫描再编译
先执行父类再执行子类
找main()方法启动程序
1.首先先去扫描Test类,发现Test类有父类Base类,先去扫描父类,发现Base类没有父类 *
2.将Base.class将在到内存的方法区,此时Base类当中的static方法执行 *
3.将Test.class将在到内存的方法区,此时Test类当中的static方法执行 *
4.main方法入栈--------->执行 new Test() 去创建Test类的对象 *
5.创建子类对象之前先创建父类对象,所以先执行Base()构造器,再执行Test()构造器
例3!!!!!
再看方法重写
父类-----A:
package Work1;
public class A {
public void run(){
System.out.println("跑得很快");
}
public void fly(){
System.out.println("飞得很高");
}
}
子类-------B
package Work1;
//继承的本质时代码的复用,子类复用父类的代码
public class B extends A{
public void run(){
System.out.println("B跑得很快");
}
}
测试类
package Work1;
//程序执行流程
//首先main方法入栈
//B b=new B();------->执行B之前,B的无参构造器会调用A的无参构造器
// 创建B对象之前,先创建其父类A的对象
//未发生重写之前:由于继承关系的存在,b能够调用A对象中的方法run() fly()
//发生重写之后:由于B类重写了run方法,重写之后,A类当中的run方法被覆盖,只能调用B类重写的run方法
// A a=new A();新建一个A类的对象,开辟一块新的内存空间,A类对象中有run() fly(),并且a可以对他们进行调用
public class Test {
public static void main(String[] args) {
B b=new B();
b.run();
b.fly();
A a=new A();
a.run();
}
}
程序执行流程
1.Test.java------javac------->Test.class
2.Test.class通过java命令,放入内存当中
3.main()入栈
4.在新建B对象前,扫描B,发现B有父类A
5.A.java------javac------->A.class
6.A.class通过java命令,放入内存当中
7.B.java-----javac-------->B.class///
8.B.class通过java命令,放入内存当中
9.开辟一块新的内存空间,新建一个A 对象,对象中包含 run() study(私有方法)方法//
子类访问不到父类当中私有的变量和方法
10.新建B对象,B对象通过继承,可以访问A对象当中的run方法,B对象中包含fly方法
继承的逻辑
方法的重写
一旦发生重写,子类对现象优先调用自身重写的方法
方法重写之前
B类方法重写之后
方法重写,并且创建A类对象
执行结果
欢迎大家点赞,评论,收藏和关注呦!!!