宜昌商城网站建设,在婚恋网站上做红娘怎么样,网站建设胡菘,wordpress回水印文章目录 一、super关键字的使用#xff08;1#xff09;为什么需要super#xff1f;#xff08;2#xff09;super的理解#xff08;3#xff09;super可以调用的结构1、super调用方法举例1举例2举例3小结 2、super调用属性举例1举例2举例3小结 3、super调用构造器引入… 文章目录 一、super关键字的使用1为什么需要super2super的理解3super可以调用的结构1、super调用方法举例1举例2举例3小结 2、super调用属性举例1举例2举例3小结 3、super调用构造器引入举例1举例2举例3举例4 4、总结super调用方法、属性super调用构造器 4小结this与super1、this和super的意义2、this和super的使用格式 5练习1、练习12、练习23、练习3 6面试题1、第一题2、第二题3、第三题4、第四题 二、子类对象实例化全过程1介绍2举例 一、super关键字的使用
1为什么需要super
举例1子类继承父类以后对父类的方法进行了重写那么在子类中是否还可以对父类中被重写的方法进行调用
可以
举例2子类继承父类以后发现子类和父类中定义了同名的属性若子类造对象就会有两个同名属性是否可以在子类中区分两个同名的属性方法可以覆盖属性不能覆盖
可以
如何调用 使用super关键字即可。
2super的理解
super的理解父类的
在子类中若想调用父类中被重写的方法就用super.方法即可若想调用父类中的属性就用super.属性即可。
若没有写super调用的就是子类中重写的方法和子类里面声明的属性。
在Java类中使用super来调用父类中的指定操作
super可用于访问父类中定义的属性super可用于调用父类中定义的成员方法super可用于在子类构造器中调用父类的构造器
注意
尤其当子父类出现同名成员时可以用super表明调用的是父类中的成员super的追溯不仅限于直接父类super和this的用法相像this代表本类对象的引用super代表父类的内存空间的标识
3super可以调用的结构
super可以调用的结构属性、方法、构造器
具体的
1、super调用方法
如果子类没有重写父类的方法只要权限修饰符允许在子类中完全可以直接调用父类的方法如果子类重写了父类的方法在子类中需要通过super.才能调用父类被重写的方法否则默认调用的子类重写的方法
举例1
观察下面代码的输出结果。
【Person.java】
package yuyi01;public class Person {//属性String name;private int age;//方法public void eat(){System.out.println(人吃饭);}public void sleep(){System.out.println(人睡觉);}
}【Student.java】
package yuyi01;public class Student extends Person {//属性String school;//方法public void study(){System.out.println(学生学习);}//重写public void eat(){System.out.println(学生多吃有营养的食物);}public void sleep(){System.out.println(学生保证每天不低于七小时睡眠);}
}【StudentTest.java】
package yuyi01;public class StudentTest {public static void main(String[] args) {Student s1new Student();s1.eat();s1.sleep();}
}输出结果 举例2
如何在子类方法Student.java里面还能够调用父类中被重写的方法呢
如果此时在子类方法里面调用eat()方法毫无疑问这个eat()方法指的是自己类里面重写的方法。如下 当然使用eat()调用和this.eat()调用效果一样前者只是省略了this.而已。
若现在想调用父类中的eat()方法很简单只需要在前面写super.即可。以不影响封装性为前提
【Student.java】
package yuyi01;public class Student extends Person {//属性String school;//重写public void eat(){System.out.println(学生多吃有营养的食物);}//...public void show(){eat(); //省略了thisthis.eat();super.eat(); //父类中的eat()方法}
}this.eat();直接在本类找找到了就直接调用本类的重写方法即可。
super.eat();直接在直接父类中找找到了就直接调用父类被重写的方法即可。
eat();是省略了this.所以本质上也是调用本类中的方法若本类中找不到才会去父类中找。
测试类【StudentTest.java】
package yuyi01;public class StudentTest {public static void main(String[] args) {Student s1new Student();//...s1.show();}
}运行结果 举例3
父类【Person.java】
package yuyi01;public class Person {//...public void doSport(){System.out.println(人运动);}
}子类【Student.java】
package yuyi01;public class Student extends Person {//...public void show1(){doSport();}
}此时子类中调用的doSport()毫无疑问是父类中的方法因为子类中没有重写它。
这时候它的前缀是啥呢
若在本类中调用方法前缀都会省略this.。调用show1()方法的时候它会在本类中找doSport()方法找不到就会去父类中找。
此时本类中没有doSport()方法就会去父类中找找到并调用。若父类中还没有就会继续往上找直到Object还没有找到就会报错了。
画个图看看 此时Sutdent类里面没有重写doSport()所以只有一个父类Person中的doSport()而已只能调用它。
从结果上说this.doSport()和super.doSport()一致但是从过程上来说this.doSport()先从本类开始找super.doSport()直接向直接父类中找。
【Student.java】
package yuyi01;public class Student extends Person {//...public void show1(){doSport();this.doSport();super.doSport();}
}测试类【StudentTest.java】
package yuyi01;public class StudentTest {public static void main(String[] args) {Student s1new Student();//...s1.show1();}
}运行结果 小结
方法前面没有super.和this. 先从子类找匹配方法如果没有再从直接父类找再没有继续往上追溯 方法前面有this. 先从子类找匹配方法如果没有再从直接父类找再没有继续往上追溯 方法前面有super. 从当前子类的直接父类找如果没有继续往上追溯
2、super调用属性
如果实例变量与局部变量重名可以在实例变量前面加this.进行区别如果子类实例变量和父类实例变量重名并且父类的该实例变量在子类仍然可见在子类中要访问父类声明的实例变量需要在父类实例变量前加super.否则默认访问的是子类自己声明的实例变量如果父子类实例变量没有重名只要权限修饰符允许在子类中完全可以直接访问父类中声明的实例变量也可以用this.实例访问也可以用super.实例变量访问
举例1
暂且不考虑权限的事情。此时父类Person和子类Student中有同名的属性id。
父类【 Person.java】
package yuyi01;public class Person {//属性String name;private int age;int id; //身份证号}子类【Student.java】
package yuyi01;public class Student extends Person {//属性String school;int id; //学号}若此时创建子类Student的对象那么它拥有几个属性呢和父类同名的属性会不会被干掉
来Debug一下 所以属性没有方法那样有覆盖之说。 属性不会覆盖而方法可以覆盖。 举例2
既然有两个同名的属性那么该如何区分它们呢
此时将父类和子类中的属性id都赋值。
父类【 Person.java】
package yuyi01;public class Person {//属性String name;private int age;int id1001; //身份证号}在子类中写一个show2()方法输出id的结果是什么呢
子类【Student.java】
package yuyi01;public class Student extends Person {//属性String school;int id1002; //学号public void show2(){System.out.println(id); //?}
}
此时输出语句并没有报错这里遵循一个就近原则。
就和之前说的get方法一样比如 再比如 当时解决办法是这样 具体关于this的讲解在这一篇博客https://blog.csdn.net/m0_55746113/article/details/134089173?spm1001.2014.3001.5502 所以此时的id会就近找一个一样的然后就找到了本类的id。
若想要父类中的id就需要加一个super.。
子类【Student.java】
package yuyi01;public class Student extends Person {//属性String school;int id1002; //学号public void show2(){System.out.println(id); //1002System.out.println(this.id); //1002System.out.println(super.id); //1001}
}
测试类【StudentTest.java】
package yuyi01;public class StudentTest {public static void main(String[] args) {Student s1new Student();//...System.out.println();s1.show2();}
}运行结果 举例3
父类【Person.java】
package yuyi01;public class Person {//属性String name;//...
}子类【Student.java】
package yuyi01;/*** ClassName: Student* Package: yuyi04* Description:** Author 雨翼轻尘* Create 2023/10/29 0029 16:40*/
public class Student extends Person {//属性String school;int id1002; //学号//方法public void show3(){System.out.println(name); //这样写就相当于省略了thisSystem.out.println(this.name);System.out.println(super.name);}
}
name先在当前类里面找若没有找到就去父类中找。
从结果上三个输出值是一样的但从过程上来说name先找本类再找父类super.name直接找父类。
测试类【StudentTest.java】
package yuyi01;public class StudentTest {public static void main(String[] args) {Student s1new Student();s1.show3();}
}输出结果 加super与this就是区分重名的属性重写的方法。
若没有重名属性和重写的方法this与super加不加无所谓只不过一个本类找一个直接父类找过程上有区别结果上没有区别。
若是父类中没有的属性本类中有用super直接父类中找是会报错的。 小结
总结起点不同就近原则
变量前面没有super.和this. 在构造器、代码块、方法中如果出现使用某个变量先查看是否是当前块声明的局部变量如果不是局部变量先从当前执行代码的本类去找成员变量如果从当前执行代码的本类中没有找到会往上找父类声明的成员变量权限修饰符允许在子类中访问的 变量前面有this. 通过this找成员变量时先从当前执行代码的本类去找成员变量如果从当前执行代码的本类中没有找到会往上找父类声明的成员变量权限修饰符允许在子类中访问的 变量前面super. 通过super找成员变量直接从当前执行代码的直接父类去找成员变量权限修饰符允许在子类中访问的如果直接父类没有就去父类的父类中找权限修饰符允许在子类中访问的
特别说明应该避免子类声明和父类重名的成员变量
3、super调用构造器
引入
为何要调用构造器
比如在Student类里new了一个Student对象可以通过s1调用属性、方法。
【Student.java】
package yuyi01;public class Student extends Person {//属性String school;int id1002; //学号}若此时父类Person里面的name属性没有限制那么在测试里面可以调用name属性。 这里我们知道内存中有name属性才直接调用它。
可我们new的是Student相当于调用的是Student的构造器会加载Student的结构那为啥还会加载父类的结构呢为啥内存中有
name属性)这里就涉及到super调用构造器的问题。
举例1
① 子类继承父类时不会继承父类的构造器构造器只有在同名的类里面才有。只能通过“super(形参列表)”的方式调用父类指定的构造器。
父类【Person.java】
package yuyi01;public class Person {//属性String name;private int age;int id1001; //身份证号//构造器public Person() {}public Person(String name, int age) {this.name name;this.age age;}public Person(String name, int age, int id) {this.name name;this.age age;this.id id;}
}子类【Student.java】
package yuyi01;public class Student extends Person {//属性String school;int id1002; //学号//测试super调用父类的构造器public Student(){}public Student(String name,int age){}
}比如在子类中调用父类中的空参构造器 举例2
父类【Person.java】
package yuyi01;public class Person {//构造器public Person() {System.out.println(Person()...);}
}子类【Student.java】
package yuyi01;public class Student extends Person {//测试super调用父类的构造器public Student(){super(); //调用父类中空参的构造器System.out.println(Student()...);}
}测试类【StudentTest.java】
package yuyi01;public class StudentTest {public static void main(String[] args) {Student s2new Student();}
}输出结果 当我们调用子类构造器创建对象的时候先调用父类构造器输出Person()...然后再输出Student()...。如下 可以在子类构造器中调用父类的构造器格式就是super(形参列表)。 举例3
② 规定“super(形参列表)”必须声明在构造器的首行。和this很像
如下 ③ 我们前面讲过在构造器的首行可以使用this(形参列表)调用本类中重载的构造器 结合②结论在构造器的首行“this(形参列表)” 和 super(形参列表)只能二选一。
比如 ④ 如果在子类构造器的首行既没有显示调用this(形参列表)“也没有显式调用super(形参列表)” 则子类此构造器默认调用super()即调用父类中空参的构造器。
父类【Person.java】
package yuyi01;public class Person {//构造器public Person() {System.out.println(Person()...);}}子类【Student.java】
package yuyi01;public class Student extends Person {public Student(String name,int age){//没有显示调用父类中空参的构造器}
}测试类【StudentTest.java】
package yuyi01;public class StudentTest {public static void main(String[] args) {Student s3new Student(Tom,13);}
}输出结果 在Student(String name,int age)构造器首行并没有写this(形参列表)也没有写super(形参列表)。此时会默认是Super()而且是空参的。
来Debug看一下 进入构造器了如下 再下一步 所以在调Student构造器的时候没有写this也没有super语句会默认父类空参构造器。
若此时将空参构造器注释掉会发现子类中两个构造器都会报错。第一个是显示调用但没有找到空参构造器就会报错第二个虽然没有显示调用谁但是默认调用了空参构造器也没有找到所以也会报错。如下 ⑤ 由③和④得到结论子类的任何一个构造器中要么会调用本类中重载的构造器要么会调用父类的构造器。 只能是这两种情况之一。
画个图瞅瞅 ⑥ 由⑤得到一个类中声明有n个构造器最多有n-1个构造器中使用了this(形参列表)“若有n个就会形成一个环递归了则剩下的那个一定使用super(形参列表)”显示或者默认。
子类中的任何一个构造器都会直接或间接地调用父类的构造器。如下 开发中常见错误 如果子类构造器中既未显式调用父类或本类的构造器且父类中又没有空参的构造器则编译出错。 调用父类构造器不是为了造对象造对象需要搭配new调用父类构造器是为了初始化信息–比如将父类的属性、方法加载到内存中。 举例4
父类【Person.java】
package yuyi01;public class Person {//属性String name;private int age;int id1001; //身份证号//方法public int getAge() {return age;}public void setAge(int age) {this.age age;}//构造器public Person() {System.out.println(Person()...);}
}子类【Student.java】
package yuyi01;public class Student extends Person {//属性String school;int id1002; //学号public Student(String name,int age){//没有显示调用父类中空参的构造器setAge(age);super.namename; //当前类里面没有name属性这里super也可以写成this}
}上面的写法很Low若父类Person中有这样的构造器
package yuyi01;public class Person {//属性String name;private int age;int id1001; //身份证号//构造器public Person() {System.out.println(Person()...);}public Person(String name, int age) {this.name name;this.age age;}}子类可以这样写
package yuyi01;public class Student extends Person {//属性String school;int id1002; //学号public Student(String name,int age){super(name,age);}
}那么子类就可以直接调用父类中的构造器如下若是没有写调用的就是父类中的空参构造器Person() 以后声明子类构造器的时候构造器的首行就可以调用父类指定的结构了。
4、总结
子类继承父类以后super关键字使用的前提是基于继承我们就可以在子类的方法或构造器中调用父类中声明的属性或方法。满足封装性的前提下
super调用方法、属性
️如何调用呢
需要使用super.的结构表示调用父类的属性或方法。
一般情况下我们可以考虑省略super.的结构。
但是如果出现子类重写了父类的方法或子父类中出现了同名的属性时则必须使用super.的声明显式地调用父类被重写的方法或父类中声明的同名的属性。
特别说明应该避免子类声明和父类重名的成员变量方法没法避开
在阿里的开发规范等文档中都做出明确说明 super调用构造器
① 子类继承父类时不会继承父类的构造器。只能通过“super(形参列表)”的方式调用父类指定的构造器。
② 规定“super(形参列表)”必须声明在构造器的首行。
③ 我们前面讲过在构造器的首行可以使用this(形参列表)调用本类中重载的构造器 结合②结论在构造器的首行“this(形参列表)” 和 super(形参列表)只能二选一。
④ 如果在子类构造器的首行既没有显示调用this(形参列表)“也没有显式调用super(形参列表)” 则子类此构造器默认调用super()即调用父类中空参的构造器。
⑤ 由③和④得到结论子类的任何一个构造器中要么会调用本类中重载的构造器要么会调用父类的构造器。 只能是这两种情况之一。
⑥ 由⑤得到一个类中声明有n个构造器最多有n-1个构造器中使用了this(形参列表)“ 则剩下的那个一定使用super(形参列表)”。
– 我们在通过子类的构造器创建对象时一定在调用子类构造器的过程中直接或间接的调用到父类的构造器。 也正因为调用过父类的构造器我们才会将父类中声明的属性或方法加载到内存中供子类对象使用。
情景举例1
class A{}
class B extends A{}class Test{public static void main(String[] args){B b new B();//A类和B类都是默认有一个无参构造B类的默认无参构造中还会默认调用A类的默认无参构造//但是因为都是默认的没有打印语句看不出来}
}情景举例2
class A{A(){System.out.println(A类无参构造器);}
}
class B extends A{}
class Test{public static void main(String[] args){B b new B();//A类显示声明一个无参构造//B类默认有一个无参构造//B类的默认无参构造中会默认调用A类的无参构造//可以看到会输出“A类无参构造器}
}情景举例3
class A{A(){System.out.println(A类无参构造器);}
}
class B extends A{B(){System.out.println(B类无参构造器);}
}
class Test{public static void main(String[] args){B b new B();//A类显示声明一个无参构造//B类显示声明一个无参构造 //B类的无参构造中虽然没有写super()但是仍然会默认调用A类的无参构造//可以看到会输出“A类无参构造器和B类无参构造器)}
}情景举例4
class A{A(){System.out.println(A类无参构造器);}
}
class B extends A{B(){super();System.out.println(B类无参构造器);}
}
class Test{public static void main(String[] args){B b new B();//A类显示声明一个无参构造//B类显示声明一个无参构造 //B类的无参构造中明确写了super()表示调用A类的无参构造//可以看到会输出“A类无参构造器和B类无参构造器)}
}情景举例5
class A{A(int a){System.out.println(A类有参构造器);}
}
class B extends A{B(){System.out.println(B类无参构造器);}
}
class Test05{public static void main(String[] args){B b new B();//A类显示声明一个有参构造没有写无参构造那么A类就没有无参构造了//B类显示声明一个无参构造 //B类的无参构造没有写super(...)表示默认调用A类的无参构造//编译报错因为A类没有无参构造}
}情景举例6
class A{A(int a){System.out.println(A类有参构造器);}
}
class B extends A{B(){super();System.out.println(B类无参构造器);}
}
class Test06{public static void main(String[] args){B b new B();//A类显示声明一个有参构造没有写无参构造那么A类就没有无参构造了//B类显示声明一个无参构造 //B类的无参构造明确写super()表示调用A类的无参构造//编译报错因为A类没有无参构造}
}情景举例7
class A{A(int a){System.out.println(A类有参构造器);}
}
class B extends A{B(int a){super(a);System.out.println(B类有参构造器);}
}
class Test07{public static void main(String[] args){B b new B(10);//A类显示声明一个有参构造没有写无参构造那么A类就没有无参构造了//B类显示声明一个有参构造 //B类的有参构造明确写super(a)表示调用A类的有参构造//会打印“A类有参构造器和B类有参构造器}
}情景举例8
class A{A(){System.out.println(A类无参构造器);}A(int a){System.out.println(A类有参构造器);}
}
class B extends A{B(){super();//可以省略调用父类的无参构造System.out.println(B类无参构造器);}B(int a){super(a);//调用父类有参构造System.out.println(B类有参构造器);}
}
class Test8{public static void main(String[] args){B b1 new B();B b2 new B(10);}
}4小结this与super
1、this和super的意义
this当前对象
在构造器和非静态代码块中表示正在new的对象在实例方法中表示调用当前方法的对象
super引用父类声明的成员
2、this和super的使用格式
this this.成员变量表示当前对象的某个成员变量而不是局部变量this.成员方法表示当前对象的某个成员方法完全可以省略this.this()或this(实参列表)调用另一个构造器协助当前对象的实例化只能在构造器首行只会找本类的构造器找不到就报错 super super.成员变量表示当前对象的某个成员变量该成员变量在父类中声明的super.成员方法表示当前对象的某个成员方法该成员方法在父类中声明的super()或super(实参列表)调用父类的构造器协助当前对象的实例化只能在构造器首行只会找直接父类的对应构造器找不到就报错
5练习
1、练习1
题目描述
修改方法重写的练习2中定义的类Kids中employeed()方法在该方法中调用父类ManKind的employeed()方法 然后再输出but Kids should study and no job.
【Kids.java】
package yuyi02;/*** ClassName: Kids* Package: yuyi05* Description:修改继承内容的练习1中定义的类Kids在Kids中重新定义employeed()方法覆盖父类ManKind中定义的employeed()方法输出Kids should study and no job.* Author 雨翼轻尘* Create 2023/10/30 0030 10:56*/
public class Kids extends Mankind { //父类中声明的属性和方法都被继承到子类了构造器就不提了。后边提super关键字的时候会提到在子类当中调用父类中的构造器private int yearOld;public int getYearOld() {return yearOld;}public void setYearOld(int yearOld) {this.yearOld yearOld;}public void printAge(){System.out.println(I am yearOld years old);}Overridepublic void employeed() {System.out.println(Kids should study and no job.);}//构造器public Kids(){}public Kids(int yearOld){this.yearOldyearOld;}//把父类中的属性也做一个赋值包括自己的属性public Kids(int sex, int salary,int yearOld){this.yearOldyearOld;//sex、salary两个 属性是父类继承过来的怎么给他们赋值setSex(sex);setSalary(salary);}
}【Mankind.java】
package yuyi02;/*** ClassName: Mankind* Package: yuyi05* Description:* (1)定义一个ManKind类包括* 成员变量int sex和int salary* - 方法void manOrWoman()根据sex的值显示“man”(sex1)或者“woman”(sex0)** - 方法void employeed()根据salary的值显示“no job”(salary0)或者“ job”(salary!0)。* Author 雨翼轻尘* Create 2023/10/30 0030 10:32*/
public class Mankind {//属性private int sex;private int salary;//方法public int getSex() {return sex;}public void setSex(int sex) {this.sex sex;}public int getSalary() {return salary;}public void setSalary(int salary) {this.salary salary;}public void manOrWoman(){if(sex1){System.out.println(man);} else if (sex0) {System.out.println(woman);}}public void employeed(){if(salary0){System.out.println(no job);} else {System.out.println(job);}}//构造器public Mankind() {}public Mankind(int sex, int salary) {this.sex sex;this.salary salary;}
}【KidsTest.java】
package yuyi02;/*** ClassName: KidsTest* Package: yuyi05* Description:*(3)定义类KidsTest在类的main方法中实例化Kids的对象someKid用该对象访问其父类的成员变量及方法。* Author 雨翼轻尘* Create 2023/10/30 0030 10:58*/
public class KidsTest {public static void main(String[] args) {Kids someKidnew Kids();someKid.setSex(1);someKid.setSalary(100);someKid.setYearOld(12);//Kids类自己声明的方法someKid.printAge();//来自于父类中声明的方法someKid.manOrWoman();someKid.employeed();//System.out.println(*************);someKid.employeed();}
}代码
【 Kids.java】
package yuyi02;/*** ClassName: Kids* Package: yuyi05* Description:修改方法重写的练习2中定义的类Kids中employeed()方法在该方法中调用父类ManKind的employeed()方法然后再输出but Kids should study and no job.* Author 雨翼轻尘* Create 2023/11/4 0030 10:56*/
public class Kids extends Mankind { //父类中声明的属性和方法都被继承到子类了构造器就不提了。后边提super关键字的时候会提到在子类当中调用父类中的构造器//...Overridepublic void employeed() {//在子类中调用父类中被重写的方法super.employeed(); //先去调用父类中的employeed()方法System.out.println(but Kids should study and no job.);}//...
}【Mankind.java】
package yuyi02;public class Mankind {//...public void employeed(){if(salary0){System.out.println(no job);} else {System.out.println(job);}}
}【KidsTest.java】
package yuyi02;public class KidsTest {public static void main(String[] args) {//...Kids someKidnew Kids();someKid.employeed();}
}输出结果 2、练习2
题目描述
在Cylinder类中修改求表面积的方法findArea()和求体积的方法findVolume(),使用上super。
【Circle.java】
package yuyi03;/*** ClassName: Circle* Package: yuyi06* Description:** Author 雨翼轻尘* Create 2023/10/31 0031 10:07*/
public class Circle {//属性private double radius; //半径//方法public void setRadius(double radius){this.radiusradius;}public double getRadius(){return radius;}//求圆的面积public double findArea(){return Math.PI*radius*radius;}//构造器public Circle(){radius1;}
}【Cylinder.java】
package yuyi03;/*** ClassName: Cylinder* Package: yuyi06* Description:* 圆柱类* Author 雨翼轻尘* Create 2023/10/31 0031 10:19*/
public class Cylinder extends Circle {//属性private double length; //高//方法public void setLength(double length){this.lengthlength;}public double getLength(){return length;}//求圆柱的体积public double findVolume(){return Math.PI*getRadius()*getRadius()*getLength(); //底面积*高//return findArea()*getLength(); //错误的}//构造器public Cylinder(){length1;}//求表面积Overridepublic double findArea() {return Math.PI*getRadius()*getRadius()*22*Math.PI*getRadius()*getLength();}
}【CylinderTest.java】
package yuyi03;/*** ClassName: CylinderTest* Package: yuyi06* Description:** Author 雨翼轻尘* Create 2023/10/31 0031 10:29*/
public class CylinderTest {public static void main(String[] args) {Cylinder cynew Cylinder();cy.setRadius(2.3);cy.setLength(1.4);System.out.println(圆柱的体积为 cy.findVolume());System.out.println(圆柱的表面积为 cy.findArea());}
}代码
【Cylinder.java】
package yuyi03;public class Cylinder extends Circle {//...//求圆柱的体积public double findVolume(){//return Math.PI*getRadius()*getRadius()*getLength(); //底面积*高 正确的//return findArea()*getLength(); //错误的return super.findArea()*getLength();}//...//求表面积Overridepublic double findArea() {return Math.PI*getRadius()*getRadius()*22*Math.PI*getRadius()*getLength();}
}【Circle.java】
package yuyi03;public class Circle {//...//求圆的面积public double findArea(){return Math.PI*radius*radius;}
}【CylinderTest.java】
package yuyi03;public class CylinderTest {public static void main(String[] args) {Cylinder cynew Cylinder();cy.setRadius(2.3);cy.setLength(1.4);System.out.println(圆柱的体积为 cy.findVolume());System.out.println(圆柱的表面积为 cy.findArea());}
}输出结果 3、练习3
题目描述
①写一个名为Account的类模拟账户。该类的属性和方法如下图所示。 该类包括的属性账号id余额balance年利率annualInterestRate
包含的方法访问器方法getter和setter方法返回月利率的方法getMonthlyInterest()取款方法withdraw()存款方法deposit()。
写一个用户程序测试Account类。在用户程序中创建一个账号为1122、余额为20000、年利率4.5%的Account对象。
使用withdraw方法提款30000元并打印余额。
再使用withdraw方法提款2500元使用deposit方法存款3000元然后打印余额和月利率。
提示在提款方法withdraw中需要判断用户余额是否能够满足提款数额的要求如果不能应给出提示。
运行结果如图所示。 ②创建Account类的一个子类CheckAccount代表可透支的账户该账户中定义一个属性overdraft代表可透支限额。
在CheckAccount类中重写withdraw方法其算法如下
————————————————————————————————————————
如果取款金额账户余额
可直接取款
如果取款金额账户余额
计算需要透支的额度
判断可透支额overdraft是否足够支付本次透支需要如果可以
将账户余额修改为0冲减可透支金额
如果不可以
提示用户超过可透支额的限额
————————————————————————————————————————
要求写一个用户程序测试CheckAccount类。
在用户程序中创建一个账号为1122、余额为20000、年利率4.5%可透支限额为5000元的CheckAccount对象。
使用withdraw方法提款5000元并打印账户余额和可透支额。
再使用withdraw方法提款18000元并打印账户余额和可透支额。
再使用withdraw方法提款3000元并打印账户余额和可透支额。
提示
1子类CheckAccount的构造方法需要将从父类继承的3个属性和子类自己的属性全部初始化。
2父类Account的属性balance被设置为private但在子类CheckAccount的withdraw方法中需要修改它的值因此应修改父类的balance属性定义其为protected。
运行结果如下图所示。 代码①
【Account.java】
package yuyi04;/*** ClassName: Account* Package: yuyi04* Description:** Author 雨翼轻尘* Create 2023/11/4 0004 8:29*/
public class Account {//属性private int id; //账户private double balance; //余额private double annualInterestRate; //年利率//构造器public Account(int id,double balance,double annualInterestRate){//super();this.idid;this.balancebalance;this.annualInterestRateannualInterestRate;}//方法public void setId(int id) {this.id id;}public void setBalance(double balance) {this.balance balance;}public int getId() {return id;}public double getBalance() {return balance;}public void setAnnualInterestRate(double annualInterestRate) {this.annualInterestRate annualInterestRate;}/*** 获取月利率* return*/public double getMonthlyInterest(){return annualInterestRate / 12;}/*** 取钱曹操作* param amount 要取的钱数*/public void withdraw(double amount){if(balanceamount){balance-amount;}else{System.out.println(余额不足);}}/*** 存钱操作* param amount 要存的额度*/public void deposit(double amount){if(amount0){balanceamount;}}
}【AccountTest.java】
package yuyi04;/*** ClassName: AccountTest* Package: yuyi04* Description:* 写一个用户程序测试Account类。在用户程序中创建一个账号为1122、余额为20000、年利率4.5%的Account对象。* 使用withdraw方法提款30000元并打印余额。* 再使用withdraw方法提款2500元使用deposit方法存款3000元然后打印余额和月利率。* Author 雨翼轻尘* Create 2023/11/4 0004 10:46*/
public class AccountTest {public static void main(String[] args) {Account acctnew Account(1122,20000,0.045);acct.withdraw(30000);System.out.println(您的账户余额为acct.getBalance());acct.withdraw(2500);acct.deposit(3000);System.out.println(您的账户余额为 acct.getBalance());System.out.println(月利率为 acct.getMonthlyInterest());}
}运行结果① 代码②
【Account.java】
package yuyi04;/*** ClassName: Account* Package: yuyi04* Description:** Author 雨翼轻尘* Create 2023/11/4 0004 8:29*/
public class Account {//属性private int id; //账户private double balance; //余额private double annualInterestRate; //年利率//构造器public Account(int id,double balance,double annualInterestRate){//super();this.idid;this.balancebalance;this.annualInterestRateannualInterestRate;}//方法public void setId(int id) {this.id id;}/*public void setBalance(double balance) {this.balance balance;}*/public int getId() {return id;}public double getBalance() {return balance;}public void setAnnualInterestRate(double annualInterestRate) {this.annualInterestRate annualInterestRate;}/*** 获取月利率* return*/public double getMonthlyInterest(){return annualInterestRate / 12;}/*** 取钱曹操作* param amount 要取的钱数*/public void withdraw(double amount){if(balanceamount){balance-amount;}else{System.out.println(余额不足);}}/*** 存钱操作* param amount 要存的额度*/public void deposit(double amount){if(amount0){balanceamount;}}
}【CheckAccount.java】
package yuyi04;/*** ClassName: CheckAccount* Package: yuyi04* Description:* 创建Account类的一个子类CheckAccount代表可透支的账户该账户中定义一个属性overdraft代表可透支限额。* Author 雨翼轻尘* Create 2023/11/4 0004 14:51*/
public class CheckAccount extends Account{//属性private double overdraft; //可透支限额//方法public double getOverdraft() {return overdraft;}public void setOverdraft(double overdraft) {this.overdraft overdraft;}//重写withdraw方法/*** 针对于可透支的账户的取钱操作* param amount 要取的钱数*/public void withdraw(double amount){if(getBalance()amount){//错误的:左右结果都是一个值何来赋值一说//getBalance()getBalance()-amount;//正确的super.withdraw(amount); //super别去掉了这里调用的是父类的withdraw方法} else if (getBalance()overdraftamount) {overdraft-amount-getBalance(); //可透支的限额剩余量super.withdraw(getBalance()); //把原本账户的钱取光}else{System.out.println(超过可透支限额);}}//构造器public CheckAccount(int id,double balance,double annualInterestRate){super(id,balance,annualInterestRate);}public CheckAccount(int id,double balance,double annualInterestRate,double overdraft){super(id,balance,annualInterestRate);this.overdraftoverdraft;}
}【CheckAccountTest.java】
package yuyi04;/*** ClassName: CheckAccountTest* Package: yuyi04* Description:* 要求写一个用户程序测试CheckAccount类。* 在用户程序中创建一个账号为1122、余额为20000、年利率4.5%可透支限额为5000元的CheckAccount对象。** 使用withdraw方法提款5000元并打印账户余额和可透支额。* 再使用withdraw方法提款18000元并打印账户余额和可透支额。* 再使用withdraw方法提款3000元并打印账户余额和可透支额。** Author 雨翼轻尘* Create 2023/11/4 0004 22:05*/
public class CheckAccountTest {public static void main(String[] args) {CheckAccount checkAccountnew CheckAccount(1122,20000,0.045,5000);checkAccount.withdraw(5000);System.out.println(您的账户余额为 checkAccount.getBalance());System.out.println(您的可透支额为 checkAccount.getOverdraft());checkAccount.withdraw(18000);System.out.println(您的账户余额为 checkAccount.getBalance());System.out.println(您的可透支额为 checkAccount.getOverdraft());checkAccount.withdraw(3000);System.out.println(您的账户余额为 checkAccount.getBalance());System.out.println(您的可透支额为 checkAccount.getOverdraft());}
}输出结果 ⚡注意
【注意一】
当我们写完第一问的时候第二问写CHeckAccount继承于Account就会报错。
如下 这是为哈呢
在声明一个类没有显示写构造器的时候会默认有一个空参的构造器。任何一个构造器的首行要么写this(形参列表)要么是super(形参列表)。若现在构造器也没有写那就是默认super()。
而现在父类Account里面根本没有提供空参构造器所以会报错。 有两种解决办法。
第一种是给父类提供空参的构造器
package yuyi04;public class Account {//...//构造器//空参构造器public Account(){}public Account(int id,double balance,double annualInterestRate){//super();this.idid;this.balancebalance;this.annualInterestRateannualInterestRate;}
}第二种可以直接调用有参的构造器 【注意二】
CheckAccount类里面重写的withdraw方法。
package yuyi04;public class CheckAccount extends Account{//...//重写withdraw方法/*** 针对于可透支的账户的取钱操作* param amount 要取的钱数*/public void withdraw(double amount){if(getBalance()amount){//错误的:左右结果都是一个值何来赋值一说//getBalance()getBalance()-amount;//正确的super.withdraw(amount); //super别去掉了这里调用的是父类的withdraw方法} else if (getBalance()overdraftamount) {overdraft-amount-getBalance(); //可透支的限额剩余量super.withdraw(getBalance()); //把原本账户的钱取光}else{System.out.println(超过可透支限额);}}
}这里很容易弄混 【小Tips】
按住CtrlShift向上方向键本行与上一行互换
【Super的使用】
①子类重写的方法里面调用父类被重写的方法 ② 6面试题
1、第一题
如下代码输出结果是多少
package com.atguigu05._super.interview;/*** 判断运行结果** author 雨翼轻尘* create 2023/11/5*/
public class Interview01 {public static void main(String[] args) {new A(new B());}
}class A {public A() {System.out.println(A);}public A(B b) {this();System.out.println(AB);}
}class B {public B() {System.out.println(B);}
}
最终输出结果是 分析一下看图 2、第二题
如下代码输出结果是多少
package com.atguigu05._super.interview;/*** 判断运行结果** author 雨翼轻尘* create 2023/11/5*/
public class Interview01 {public static void main(String[] args) {new A(new B());}
}class A {public A() {System.out.println(A);}public A(B b) {this();System.out.println(AB);}
}class B extends A{public B() {System.out.println(B);}
}最终输出结果是 分析一下看图 3、第三题
如下代码输出结果是多少
package yuyi05;/*** author 雨翼轻尘* create 2023/11/5*/
public class Interview02{public static void main(String[] args) {Father f new Father();Son s new Son();System.out.println(f.getInfo());//atyuyiSystem.out.println(s.getInfo()); //atyuyis.test();//atyuyi atyuyiSystem.out.println(-----------------);s.setInfo(轻尘);System.out.println(f.getInfo());//atyuyiSystem.out.println(s.getInfo());//轻尘s.test(); //轻尘 轻尘}
}
class Father{private String info atyuyi;public void setInfo(String info){this.info info;}public String getInfo(){return info;}
}
class Son extends Father{private String info 雨翼轻尘;public void test(){System.out.println(this.getInfo());System.out.println(super.getInfo());}
}最终输出结果是 分析一下看图
①
②
③
④
4、第四题
如下代码输出结果是多少
package yuyi05;/*** author 雨翼轻尘* create 2023/11/5*/
public class Interview02{public static void main(String[] args) {Father f new Father();Son s new Son();System.out.println(f.getInfo());//返回最近的info即本类的atyuyiSystem.out.println(s.getInfo()); //返回最近的info即本类的雨翼轻尘s.test();//“雨翼轻尘” atyuyiSystem.out.println(-----------------);s.setInfo(轻尘);System.out.println(f.getInfo());//atyuyiSystem.out.println(s.getInfo());//雨翼轻尘s.test(); //雨翼轻尘 轻尘}
}
class Father{private String info atyuyi;public void setInfo(String info){this.info info;}public String getInfo(){return info;}
}
class Son extends Father{private String info 雨翼轻尘;public void test(){System.out.println(this.getInfo());System.out.println(super.getInfo());}//重写public String getInfo(){return info;}
}最终输出结果是 分析一下看图
①
②
二、子类对象实例化全过程
1介绍
调用子类构造器去创建对象的时候会直接或间接地调用父类地构造器。
整个过程其实可以理解为关于某个类的对象在创建这个对象的过程当中是什么样的场景。
Dog dog new Dog(小花,小红);2举例
代码举例
class Creature{ //生物类//声明属性、方法、构造器
}class Animal extends Creature{ //动物类}class Dog extends Animal{ //狗类}class DogTest{public static void main(String[] args){//子类对象DOg在实例化的过程当中整个过程是怎样的呢Dog dog new Dog(); //创建DOg的对象中涉及到父类、父类的父类加载的过程//通过dog调用属性、方法只要是在Animal或Creature里面定义的属性、方法dog.xxx();dog.yyy ...;}
}从结果的角度来看体现为类的继承性
当我们创建子类对象后子类对象就获取了其父类所有父类包括直接父类、间接父类中声明的所有的属性和方法在权限允许的情况下可以直接调用。
从过程的角度来看继承性它在内存层面是怎么保证它是能够调用的
当我们通过子类的构造器创建对象时子类的构造器一定会直接或间接地调用到其父类的构造器而其父类的构造器同样会直接或间接地调用到其父类的构造器…直到调用了Object类中的构造器为止。
正因为我们调用过子类所有的父类的构造器所以我们就会将父类中声明的属性、方法加载到内存中供子类的对象使用。
问题在创建子类对象的过程中一定会调用父类中的构造器吗 yes! 先有父类的加载才有子类的加载。
问题创建子类的对象时内存中到底有几个对象 就只有一个对象只new了一次即为当前new后面构造器对应的类的对象。
①造对象–new
②构造器–初始化init 叨叨 这一篇写累死我了战线拉得很长不过值得有任何错误的地方欢迎指正