室友肝了一会原神居然学会了继承?(保姆级笔记)

26 篇文章 3 订阅

目录

类的继承

 Object类

 方法的重写

 Super关键字


类的继承

1.在Java语言中,一个类继承另一个类需要使用关键字extends

class Child extends Parent{  }

因为java只支持单继承,即一个类只能有一个父亲,所以类似下面的代码是错误的:

class Child extends Parent1,Parent2{ }

2.子类在继承父类之后,创建子类对象的同时会调用父类的构造方法。

class Parent {
public Parent()
{
System.out.println("调用父类构造方法");
}
}
class Child extends Parent{
public Child()
{
System.out.println("调用子类构造方法");
}
}
public class a{
public static void main(String[] args)
{
new Child();
}
}

 

下面是子类调用父类的属性以及本身的属性

package gh;


class f{
	int age=18;
	void kk()
	{
		System.out.println("让我康康");
	}
}
class b extends f       {
	String c="多少岁?";
	
}
public class a{
	public static void main(String[] args)
	{
		b jiebrother=new b();
		System.out.println(jiebrother.c);//调用本身属性
		System.out.println(jiebrother.age);//调用父类属性
		jiebrother.kk();//调用父类方法
	}
}

 还有爷爷,父亲,孙子模型(多继承),当然,在java里面没有爷爷类(只有父类和子类),我只是形象描述一下哈,小伙伴们不要搞错啦!

子类直接继承的父类,叫直接父类间接继承的父类,称为间接父类

package gh;

class grandfather{
public grandfather()
{
		System.out.println("调用祖父类构造方法");
}	
}
class Parent extends grandfather {
public Parent()
{
System.out.println("调用父类构造方法");
}
}
class Child extends Parent{
public Child()
{
System.out.println("调用子类构造方法");
}
}
public class a{
public static void main(String[] args)
{
new Child();
}
}

视频笔记: 一旦子类A继承父类B后,子类A就获取了父类B中声明的所有的属性和方法,特别的,父类中声明为private的方法或属性,子类继承父类以后,仍然认为获取了父类中的私有结构。只有因为封装性的影响,使得子类不能直接调用父类的结构而已。

下面利用继承性计算圆和圆柱的面积 

package gh;

public class Circle {
  private double radius;
	public Circle()//无参构造器,初始化radius为1
	{
		radius=1;
	}
public void setRadius(double radius)//设置radius
{
	this.radius=radius;
}
public  double getRadius()//得到radius
{
	return radius;
}
public double S()//求面积
{
	return Math.PI*radius*radius;
}
	
}
package gh;

public class Cylinder extends Circle//第一步先继承Circle
{
	private double  length =1;
	public Cylinder()
	{
		length=1;
	}
	public void setLength(double length)
	{
		this.length=length;
	}
	public double getLength()
	{
		return length;
	}
	public double findVolume()
	{
		return Math.PI*getRadius()*getRadius()*getLength();
	}

}
package gh;

public class Cylindertest {
public static void main(String[] args)
{
	
	Cylinder a=new Cylinder();
	a.setRadius(2.0);
	a.setLength(3.0);
	double b=a.findVolume();
	System.out.println("圆柱的体积为"+b);
	double c=a.S();
	System.out.println("圆的面积为"+c);
	
}
}

 

 Object类

Object类是比较特殊的类,它是所有类的父亲,是java类层中的最高层类。用户创建一个类时,除非已经指定要从其他类继承,否则它就是从java.lang.Object类继承而来的。java中的每个类都源于java.lang.Object类,如String类,Integer类,都是继承于Object类。由于所有类都是Object类的子类,所有在定义类时可以省略extends Object. 

class a{
}
//等价于
class a extends Object{
}

 Object类中的getClass(),notify(),notifyAll(),wait()等方法不能被重写,因为这些方法被定义为final类型。

1.getClass()方法

getClass()方法是Object类定义的方法,它会返回对象执行时的Class实例,然后使用此实例调用getName()方法可以取得类的名称。

 getClass().getname();

2.toString()方法

toString()方法的功能是将一个对象返回为字符串形式,它会返回一个String实例。在实际的应用中通常重写toString()方法,为对象提供一个特定的输出模式。当这个类转换为字符串或与字符串连接时,将自动调用重写的toString()方法。

package gh;

public class a{
String name;
int age;
public a(String name,int age)
{
	this.name=name;
	this.age=age;
}
public String toString()
{
	return "我是"+name+", 年芳"+age;
}
public static void main(String[] args)
{
	a mm=new a("灵儿",18);
	System.out.println(mm);
}
}

3.equals()方法

在java语言中,有两种比较对象的方式,分别为“==”运算符和equals()方法。两者的区别在于:“==”比较的是两个对象引用内存地址是否相等,而equals()方法比较的是两个对象的实际内容。

接下来我们处理2个对象,名字不一样,但身份证号ID一样,来判断是否是同一个人,这里我们对Object类的equals方法进行重写

package gh;

public class a{
String name;
int ID;
public a(String name,int ID)
{
	this.name=name;
	this.ID=ID;
}
public boolean equals(Object m)
{
	if(this==m)
		return true;
	if(getClass()!=m.getClass())
		return false;
	a m1=(a)m;
	if(ID!=m1.ID)//强制类型转换
		return false;	
	return true;
}
public String toString()//我们利用构造器进行初始化的时候会输入ID和名字,这里我们设置只返回名字
{
	return name;
}
public static void main(String[] args)
{
a a1=new a("jk",121);
a a2=new a("jik",22);
a a3=new a("dk",121);
System.out.println("a1与a3是否为同一人?"+(a1==a3));
System.out.println("a1与a3是否为同一人?"+a1.equals(a3));
}
}

从这里可以看出,“jk”和"dk”虽然名字不同,但是ID相同,所以用equals()方法判断出了这两个对象实际是同一个,而“==”运算符无法做出有效判断。如果两个对象的身份证号不同,或者两个对象类型都不同,equals()方法就会认为两者不是同一个人。 

 方法的重写

定义:在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的重置覆盖。在程序执行时,子类的方法将覆盖父类的方法。

要求:1.子类重写的方法必须和父类被重写的方法具有相同的方法名称参数列表。 

2.子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型

3.子类重写的方法使用的访问权限不能小于父类被重写的方法的方法的访问权限

->子类不能重写父类中声明为private权限的方法

4.子类方法抛出的异常不能大于父类方法被重写的异常

 注意:子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为static的(不是重写)。因为static方法是属于类的,子类无法覆盖父类的方法。

1. 方法重写只存在于子类和父类 ( 包括直接父类和间接父类 ) 之间。在同一个类中方法只能被重载,不
能被重写 .
2. 静态方法不能重写
1. 父类的静态方法不能被子类重写为非静态方法 // 编译出错
2. 父类的非静态方法不能被子类重写为静态方法; // 编译出错  
3. 子类可以定义与父类的静态方法同名的静态方法 ( 但是这个不是覆盖 )
  重写的语法
1. 方法名必须相同
2. 参数列表必须相同
3. 访问控制修饰符可以被扩大 , 但是不能被缩小: public protected default private
4. 抛出异常类型的范围可以被缩小 , 但是不能被扩大
ClassNotFoundException ---> Exception
5. 返回类型可以相同 , 也可以不同 , 如果不同的话 , 子类重写后的方法返回类型必须是父类方法返回(父类void子类也是void)
类型的子类型
例如 :父类方法的返回类型是 Person, 子类重写后的返回类可以是 Person 也可以是 Person
子类型,也比如父类是Object子类是String,也是可以滴!

例1

package gh;

public class student {
public student()
{
	
}
public void study()
{
	System.out.println("我应该好好学习");
}

}
package gh;

public class studentA extends student//继承父类
{
	public studentA()
	{
		
	}

	public void study() {
		System.out.println("我不要好好学习");
	}
}
package gh;

public class a{
public static void main(String[] args)
{
	studentA  A=new studentA();
	A.study();
}
}

可以看到,在main函数里调用时,最终显示的是子类对象的方法的结果,study方法重写。 

下面把父类中的study方法的权限修饰符改为private

package gh;

public class student {
public student()
{
	
}
public void ss()
{
	System.out.println("ss");
	study();
}
 private void study()
{
	System.out.println("我应该好好学习");
}

}
package gh;

public class studentA extends student//继承父类
{
	public studentA()
	{
		
	}

	public void study() {
		System.out.println("我不要好好学习");
	}
}
package gh;

public class a{
public static void main(String[] args)
{
	studentA  A=new studentA();
	A.ss();
}
}

 即

子类重写的方法使用的访问权限不能小于父类被重写的方法的方法的访问权限

->子类不能重写父类中声明为private权限的方法

 Super关键字

学习了方法的重写我们可能会遇到一个问题,在子类重写了父类的方法后,如果我们在调用方法时既可能用到重写后的方法也可能用到没重写的父类的方法,这时候我们怎样写代码去满足这个条件?这时候就需要super关键字来实现了。

public class student {
	int age=20;
public student()
{
}
public void ss()
{
	System.out.println("ss");
	study();
}
 public void study()
{
	System.out.println("还是好好学习吧你!"); 
}
}
public class studentA extends student//继承父类
{
	int age=10;
	public studentA()
	{	
	}
	public void study() {
		System.out.println("我不要好好学习");
	}
	public void test()
	{
		super.study();
		System.out.println("age="+age);
	}
}
public static void main(String[] args)
{
studentA A=new studentA();
A.test();
}
}

视频笔记: 

1.我们可以在子类是方法或构造器中。通过使用“super.属性”或"super.方法"的方式,显示的调用父类中声明的属性或方法。但是,在通常情况下,我们习惯省略“super.”       

 2.当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须是显示的使用"super.属性"的方式,声明调用的是父类中声明的属性.

 3.当子类重写了父类中的方法以后,我们想在子类方法中调用父类中被重写的方法时,则必须显示的使用"super.方法"的方式,表面调用的是父类中被重写的方法.

 下面来看父类没有无参构造器的情况

public class student {
	int age=20;
	int m=2;

	/*
	 * public student() { }
	 */
	public student(int age)
	{
		this.age=age;
	}
public void ss()
{
	System.out.println("ss");
	study();
}
 public void study()
{
	System.out.println("还是好好学习吧你!"); 
}
}
public class studentA extends student//继承父类
{
	int age=10;
	public studentA()
	{	
	}
	public void study() {
		System.out.println("我不要好好学习");
	}
	public void test()
	{
		super.study();
		System.out.println("age="+age);
	}
}
public static void main(String[] args)
{
studentA A=new studentA();
A.test();
}
}

 编译报错,子类构造器中会隐式的调用父类的无参构造器,但是父类中没有无参构造器

当super位于构造器的第二行语句时,编译报错。

1. super 调用父类构造方法,必须是 构造方法中的第一个语句
2. super 只能出现在子类的方法或者构造方法中。
3. super this 不能够同时调用构造方法。(因为 this 也是在构造方法的第一个语句)  

 视频笔记:super和this的区别:

1.this:代表所属方法的调用对象。super代表父类对象的引用空间。

2.super只有在继承条件下才能使用

子类对象的实例化过程视频笔记:

1.从结果上来看:子类继承父类以后,就获取了父类中声明的属性或方法。创建子类的对象,在堆空间中,就会加载所有父类中声明的属性。

2.从过程来看: 当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类的构造器,进而调用父类的父类的构造器。直到调用了java.lang.Object类中空参的构造器为止。正因为加载过所有的父类的结构,所以才可以看到内存中有父类的结构,子类对象才可以考虑进行调用。

 3.虽然创建子对象时调用了父类的构造器,但是自始至终就创建了一个对象,即为new子类对象 

                      学习如逆水行舟,不进则退。和小吴一起加油吧!

  • 34
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 42
    评论
评论 42
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小吴有想法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值