super关键字
-
super是一个关键字
super: super能出现在实例方法和构造方法中 super的语法是:“super.”、“super()” super不能使用在静态方法中 super.大部分情况下是可以省略的。 super.什么时候不能省略 父类和子类中有同名属性/相同方法,想在子类中访问父类的东西,“super.”不能省 super()只能出现在构造方法第一行,通过当前的构造方法去调用“父类”中其他的构造方法 目的:创建子类对象的时候,先初始化父类型特征。 super.属性名 【访问父类中的属性】 super.方法名(实参) 【访问父类的方法】 super(实参) 【调用父类的构造方法】
/* 1、super是一个关键字,全部小写 2、super和this对比着学习。 this: this能出现在实例方法和构造方法中。 this的语法是:“this.”、“this()” this不能使用在静态方法中 this.大部分情况下是可以省略的。 this.什么时候不能省略?在区分局部变量和实例变量时不能省略。 public void setName(String name){ this.name = name; } this()只能出现在构造方法第一行,通过当前的构造方法去调用“本类”中其他的构造方法。 目的:代码复用。 super: super能出现在实例方法和构造方法中 super的语法是:“super.”、“super()” super不能使用在静态方法中 super.大部分情况下是可以省略的。 super.什么时候不能省略 父类和子类中有同名属性/相同方法,想在子类中访问父类的东西,“super.”不能省 super()只能出现在构造方法第一行,通过当前的构造方法去调用“父类”中其他的构造方法。 目的:创建子类对象的时候,先初始化父类型特征 3、super() 表示通过子类的构造方法调用父类的构造方法, 通过现实模拟这种场景:要想有儿子,先得有父亲。 4、★结论★: 当一个构造方法第一行既没有this(),又没有super()时,默认会有一个super() 表示通过当前子类的构造方法调用父类的无参构造方法,所以必须保证父类的无参构造方法存在 注意: this()与super()不能共存在同一构造方法中,因为他们都必须在构造方法的第一行 5、无论如何: 父类的构造方法是一定会执行的。(百分百执行) */ public class SuperText01 { public static void main(String[] args){ new B(); } } class A{ public A(){ //这里也有super(); ,是调用所有类的父类:Object类中的构造方法 System.out.println("A类的无参构造方法执行"); } //一个类中如果没有手动提供任何构造方法,系统会默认提供一个无参数的构造方法。 //一个类如果手动提供一个构造方法,那么系统不再提供默认的无参数构造方法。 public A(int i){ //super(); //默认有这行代码 System.out.println("A类有参"); } } class B extends A{ public B(){ //子类构造方法的第一行默认有一个super()调用父类的无参数构造方法。 // 如果父类中只定义了一个有参数的构造方法,即没有定义无参数的构造方法,调用子类的构造方法时报错: //super(1); /* 错误:无法将类 A中的构造器 A应用到给定类型; 需要: int 找到: 没有参数 原因: 实际参数列表和形式参数列表长度不同 原因:在父类有参构造方法中第一行,默认有一个super(),而我们没有定义无参构造,但B类中的有参构造方第一行默认是super()方法,而父类只有有参构造,需要int参数,而调用时是没有参数,所以报错。 */ //解决方法:在父类中写出无参构造方法,或在子类中无参构造方法的第一行super()中传递相对应的类型及参数: //super(); //这里默认有一行代码:super(); this("zhangsan"); //但有了this("zhangsan");就不再有super();这句代码。 System.out.println("B类的无参构造方法执行"); } public B(String name){ //super(); //默认有这行代码 System.out.println("B类有参构造方法"); } }
-
判断程序输出顺序
/* 判断程序输出顺序 在java语言中不管是什么对象,老祖宗的Object无参构造方法一定执行,不过Object中无参数构造方法什么都不输出。 (Object类的无参构造方法处于“栈顶部” ) 栈的运行原理: 先进后出原则。 栈顶最后调用,最先执行结束。 */ public class SuperText02 { public static void main(String[] args){ new CC(); } } /* class Object{ public Object(){} //最后调用到老祖宗类中的无参构造方法,然后这个方法最先弹出去,因为是在栈的顶部 //执行完毕之后,最先弹栈出去。 } */ class AA extends Object{ public AA(){ System.out.println("1 AA无参执行"); } } class BB extends AA{ public BB(){ System.out.println("BB无参执行"); } public BB(String name){ System.out.println("2 BB有参执行"); } } class CC extends BB{ public CC(){//最先调用,最后结束 this("zhangsan"); System.out.println("5 CC无参执行"); } public CC(String name){ this(name,20); System.out.println("4 CC有一参执行"); } public CC(String name,int age){ super(name); System.out.println("3 CC有两个参数的执行"); } }
-
super什么时候用,代表什么,super的运行原理内存图
/* 1、举个例子: 在恰当的时间使用:super(实际参数列表); 2、注意:在构造方法执行过程中一连串调用了父类的构造方法, 父类的构造方法又继续调用它的父类的构造方法,但实际上只创建了一个对象。 3、super(实参) 的作用:初始化当前对象的父类型特征,并不是创建新对象。实际上对象只创建了一个。 4、super关键字代表:“当前对象”的那部分父类型特征。 如:我继承了我父亲的一部分特征 包括:眼睛、肤色等 super代表的就是“眼睛、肤色等” “眼睛、肤色”虽然是继承的父亲的,但是在我的身上。 */ public class SuperText03 { public static void main(String[] args){ CreditAccount ca1 = new CreditAccount(); System.out.println(ca1.getActNo()+"的余额:"+ca1.getBalance()+" \t他的信誉为:"+ca1.getCredit()); CreditAccount ca2 = new CreditAccount("123456",10000.0,0.9999 ); System.out.println(ca2.getActNo()+"的余额:"+ca2.getBalance()+" \t他的信誉为:"+ca2.getCredit()); } } //银行账户类 //账户属性:账户、余额 class Account1{ private String actNo; private double balance; public Account1(){} public Account1(String actNo,double balance){ this.actNo = actNo; this.balance = balance; } public String getActNo(){ return actNo; } public void setActNo(String actNo){ this.actNo = actNo; } public double getBalance(){ return balance; } public void setBalance(double balance){ this.balance = balance; } } //其他类型的账户:信用卡账户 //账号、余额、信誉度 class CreditAccount extends Account1{//子类 private double credit; public CreditAccount(){ } //提供有参数的构造方法 /* 私有属性只能在本类中访问。 错误: actNo 在 Account1 中是 private 访问控制 balance 在 Account1 中是 private 访问控制 public CreditAccount(String actNo,double balance,double credit){ this.actNo = actNo; this.balance = balance; this.credit = credit; } */ public CreditAccount(String actNo,double balance,double credit){ super(actNo,balance); this.credit = credit; } public void doSome(){ System.out.println(getActNo()); } public double getCredit(){ return credit; } public void setCredit(double credit){ this.credit = credit; } }
-
super 与this引用同一个变量
public class SuperText04 { public static void main(String[] args){ Vip v = new Vip("张三"); v.shopping(); } } class Customer{ String name; public Customer(){ } public Customer(String name){ this.name = name; } } class Vip extends Customer{ public Vip(){} public Vip(String name){ super(name); } public void shopping(){ //this表示当前对象 System.out.println(this.name + "正在购物"); //super表示的是当前对象的父类型特征(super是this指向的那个对象中的一块空间。) System.out.println(super.name +"正在购物"); //name前如果什么都没有,会默认加this. System.out.println(name +"正在购物"); } }
-
super什么时候不能省略?
/* 1、“this.” 和“super.”大部分情况下都是可以省略的 2、“this.”什么时候不能省略:区分实例变量和局部变量时不可以省略。 public void setName(string name){ this.name = name; } 3、“super.”什么时候不能省略? 父类中有某个(属性),子类中也有(这个属性)的,如果要在子类中访问“父类的特征”时,super.不可以省略。 */ public class SuperText05 { public static void main(String[] args){ Vip v = new Vip("张三"); v.shopping(); } } class Customer{ String name; public Customer(){ } public Customer(String name){ this.name = name; } public void doSome(){ System.out.println(this.name+"doSome"); System.out.println(name +"doSome"); /* 错误--找不到符号: 变量 name 原因:Customer类的父类是Object类,Object类中没有name属性。 System.out.println(super.name +"doSome"); */ } } class Vip extends Customer{ //假设子类中有一个同名属性 //java中允许在子类中出现和父类一样的同名变量/同名属性。 String name; public Vip(){} public Vip(String name){ super(name); //这里默认有一行代码,给本类中的实例变量赋默认值 //this.name = null; } public void shopping(){ /* java是怎么来区分子类和父类共同的特征的? this.name :当前对象的name属性。 super.name:当前对象的父类型特征的name属性。 */ //this表示当前对象,这里的name在有参构造方法执行时,赋了默认值null System.out.println(this.name + "正在购物"); //null正在购物 //super表示的是当前对象的父类型特征(super是this指向的那个对象中的一块空间。) //这里的name是继承了父类的name,所以super.name 是调用父类构造方法时传递进去的:张三。 System.out.println(super.name +"正在购物"); //张三正在购物 //name前如果什么都没有,会默认加this. ,这里的name也是本类中构造方法默认赋的null System.out.println(name +"正在购物"); //null正在购物 } }
-
super使用时后面必须有个点(.)
/* 通过测试得到结论: super 不是引用。super也不保存内存地址,super也不指向任何对象 super 只是代表当前对象内部的那一块父类型特征。 */ public class SuperText06 { //实例方方法 public void doSome(){ System.out.println(this);//SuperText06@58ceff1 //输出“引用”的时候,会自动调用引用的toString()方法 //System.out.println(this.toString());//SuperText06@58ceff1 //编译错误: 需要'.' //System.out.println(super); } /* this和super不能使用在static静态方法中。 public static void doOther(){ //错误: 无法从静态上下文中引用非静态 变量 this System.out.println(this); System.out.println(super.xx); } */ //静态方法,主方法 public static void main(String[] args) { SuperText06 st = new SuperText06(); st.doSome(); //错误: 无法从静态上下文中引用非静态 变量 this // System.out.println(this); // System.out.println(super.xx); } }
-
super.调用父类方法
/* 1、 在父和子中有同名的属性/相同的方法,如果想在子类中访问父类中的数据 必须加“super.”加以区分 2、 super.属性名 【访问父类中的类型】 super.方法名(实参) 【访问父类的方法】 super(实参) 【调用父类的构造方法】 注意:私有的属性/方法 只能在本类中访问,除了这个类都不能访问 super也不能访问父类中私有的属性/方法 */ public class SuperText07 { public static void main(String[] args){ Cat1 c = new Cat1(); c.yiDong(); } } class Animal1{ public void move(){ System.out.println("Animal move"); } } class Cat1 extends Animal1{ //对move进行重写 public void move(){ System.out.println("Cat move"); } public void yiDong(){ //this.表示这个对象的,调用(子类中)重写后的方法 this.move(); //Cat move //方法前什么都没有,自动加this. move(); //Cat move //super. 不仅可以访问属性,也可以访问方法 //super调用的是子类中父类型的特征,所以这里调用的是父类的方法。 super.move(); //Animal move } }
-
猜数字游戏
/* 一个类A有一个实例变量v,从键盘接收一个正整数作为实例变量v的初始值。 另外再定义一个类B,对A类的实例变量v进行猜测。 如果大了则提示大了 小了则提示小了 等于则提示猜测成功 */ public class Text1 { public static void main(String[] args) { //创建A对象 //A1 a = ; //创建B对象,将a对象中的值传递进去 B1 b = new B1(new A1(100)); //执行B中猜测数字的方法 java.util.Scanner s = new java.util.Scanner(System.in); while1:while(true){ System.out.print("请输入要猜测数字:"); int caiNum = s.nextInt(); b.cai(caiNum); } } } class A1{ private int v; public A1(){} public A1(int v){ this.v = v; } public int getV(){ return v; } public void setV(int v){ this.v = v; } } class B1{ //把A作为B的实例变量 //通过B猜测A,在B中创建了一个A类型的对象a private A1 a; //通常会在这里卡住,不知道将A设置为B的一个属性。(慢慢培养) public B1(){ } public B1(A1 a){ this.a = a; } public A1 getA(){ return a; } public void setA(A1 a){ this.a = a; } public void cai(int caiNum){ //实际数字 int shiJiZhi = a.getV(); if(caiNum == shiJiZhi){ System.out.println("猜对了,程序终止"); //终止程序的运行(退出JVM) System.exit(0); //退出JVM的方法。 }else if(caiNum > shiJiZhi){ System.out.println("太大了,重新猜"); }else{ System.out.println("太小了,重新猜"); } } }
-
交通工具作业
/*2、请定义一个交通工具(Vehicle)的类 其中有属性: 速度(speed) 体积(size)等等 方法移动(move()) 设置速度(setSpeed(int speed)) 加速speedUp(), 减速speedDown()等等. 最后在测试类Vehicle中的main()中实例化一个交通工具对象 并通过方法给它初始化speed,size的值并且打印出来。 另外调用加速减速的方法对速度进行改变。*/ public class HomeWork2 { public static void main(String[] args) { Vehicle v = new Vehicle(); v.setSpeed(0); v.setSize(3); System.out.println("speed:"+v.getSpeed()+"\tsize:"+v.getSize()); Vehicle v2 = new Vehicle(0,5); System.out.println("speed:"+v2.getSpeed()+"\tsize:"+v2.getSize()); //v的加速及减速 v.speedUp(10); v.speedDown(9); //v2的加速及减速 v2.speedUp(100); v2.speedDown(50); } } class Vehicle{ private int speed; private int size; public Vehicle() { } public Vehicle(int speed, int size) { this.speed = speed; this.size = size; } public int getSpeed() { return speed; } public void setSpeed(int speed) { this.speed = speed; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } public void move(){ System.out.println("交通工具:公共汽车正在行驶"); } public void speedUp(int addSpeed){ this.setSpeed(this.getSpeed()+addSpeed); System.out.println("加速后speed:"+this.getSpeed()); } public void speedDown(int subSpeed){ if(this.getSpeed()>=subSpeed){ this.setSpeed(this.getSpeed()-subSpeed); System.out.println("减速后speed:"+this.getSpeed()); }else{ System.out.println("减速错误"); } } }
-
简单计算器
/* 4、编写Java程序模拟简单的计算器。 定义名为Number的类其中有两个整型数据成员n1和n2应声明为私有。 编写构造方法赋予n1和n2初始值 再为该类定义: 加addition()、减subtration()、乘multiplication()、除division()等公有实例方法 分别对两个成员变量执行加、减、乘、除的运算。 在main方法中创建Number类的对象调用各个方法并显示计算结果 */ public class HomeWork3 { public static void main(String[] args) { Number n1 = new Number(2,2); n1.addition(); Number n2 = new Number(10,4); n2.subtration(); Number n3 = new Number(5,5); n3.multiplication(); Number n4 = new Number(9,3); System.out.println(n4.getN1()+"/"+n4.getN2()+"="+n4.division()); System.out.println(n4.division()); //还可以在方法中加判断,比如:除数不能为0等 } } class Number{ private int n1; private int n2; public Number() { } public Number(int n1, int n2) { this.n1 = n1; this.n2 = n2; } public int getN1() { return n1; } public void setN1(int n1) { this.n1 = n1; } public int getN2() { return n2; } public void setN2(int n2) { this.n2 = n2; } // 再为该类定义加addition()、减subtration()、乘multiplication()、除division()等公有实例方法 // 分别对两个成员变量执行加、减、乘、除的运算。 public void addition(){ System.out.println(this.getN1()+"+"+this.getN2()+"="+(this.getN1()+this.getN2())); } public void subtration(){ int result = this.getN1() - this.getN2(); System.out.println(n1+"-"+n2+"="+result); } public void multiplication(){ int result = n1 * n2; System.out.println(n1+"*"+n2+"="+result); } //也可以将返回值类型设置为int类型,然后在main方法中设置变量接收/直接输出 public int division(){ return this.getN1()/this.getN2(); } }
-
编写Java程序用于显示人的姓名和年龄。
/* 5、编写Java程序用于显示人的姓名和年龄。 定义一个人类Person该类中应该有两个私有属性姓名name和年龄age。 定义构造方法用来初始化数据成员。再定义显示display方法将姓名和年龄打印出来。 在main方法中创建人类的实例然后将信息显示 */ public class HomeWork4 { public static void main(String[] args) { Person p = new Person(); p.setName("张三"); p.setAge(20); p.display(); Person p2 = new Person("李四",50); p2.display(); Person p3 = new Person(); p3.display(); } } class Person{ private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void display(){ System.out.println(name+"的年龄为:"+age); } }
-
打印时、分、秒(满进/少退)
/* 3、在程序中经常要对时间进行操作但是并没有时间类型的数据。 那么我们可以自己实现一个时间类来满足程序中的需要。 定义名为MyTime的类其中应有三个整型成员时hour分minute秒second 为了保证数据的安全性这三个成员变量应声明为私有。 为MyTime类定义构造方法以方便创建对象时初始化成员变量。 再定义diaplay方法用于将时间信息打印出来。 为MyTime类添加以下方法 addSecond(int sec) addMinute(int min) addHour(int hou) subSecond(int sec) subMinute(int min) subHour(int hou) 分别对时、分、秒进行加减运算。 自己的思路:在打印的方法里进行满进/少退,满进少退的时候调用加/减 时/分/秒 的方法进行操作 打印方法前各判断了一次,也就是六次,可以尝在负数前加一个+号进行操作,具体没试过,感兴趣可自行尝试 另一种思路:在加/减 秒/分/时 的时候每个方法中设置关卡,不过这个比较麻烦。 进阶思路:把加秒的方法写出来,加 分/时 的方法可以调用加秒的方法。减的也一样 还可以把加/减 时/分/秒 的6个方法合并为3个,为:修改时/分/秒的方法,毕竟传递的参数可以自己设置符号 */ public class HomeWork5 { public static void main(String[] args) { MyTime mt = new MyTime(); mt.display(); //加 时/分/秒 测试 // mt.addSecond(3600); // mt.addMinute(1439); // mt.addHour(49); //减 时/分/秒 测试 // mt.subSecond(3599); // mt.subMinute(1379); mt.subHour(25); mt.display(); } } class MyTime{ private int hour; private int minute; private int second; public MyTime() { } public MyTime(int hour, int minute, int second) { this.hour = hour; this.minute = minute; this.second = second; } public int getHour() { return hour; } public void setHour(int hour) { this.hour = hour; } public int getMinute() { return minute; } public void setMinute(int minute) { this.minute = minute; } public int getSecond() { return second; } public void setSecond(int second) { this.second = second; } //在输出前对时/分/秒 进行满进/少退 ,只是简单的写了出来,可能不是很严谨。 public void display(){ //在这里为时/分/秒进行满60进1操作,使打印出来的时分秒满足实际要求 //这里要知道加多少分种,所以使用for循环进行循环判断 // for(int min =1;this.getSecond()>=60;this.setSecond(this.getSecond() - 60)){ // this.setMinute(this.getMinute()+min); // } //加 时/分/秒 的判断 if(this.getSecond()>=60){//如果秒数大于等于60,则进行加1分减60秒操作,调用加分减秒方法 int min = this.getSecond()/60; //这里判断有几分钟,用一个变量接收 this.addMinute(min); this.subSecond(min*60); //这里可以调用setSecond 方法,参数那里用实际的秒数与60取余,如: //this.setSecond(this.getSecond()%60); } if(this.getMinute()>=60){//如果分钟数大于等于60,则进行加1时减60分操作,调用加时减分方法 this.addHour(this.getMinute()/60);//也可以直接传进去方法 //只要超过60分钟,有几个60分钟就减去几个60分钟 //这里必须是先用分钟数除去60判断有几个整的60,然后再*60就是已经进为整小时的分钟数 this.subMinute((this.getMinute()/60)*60); } if(this.getHour()>=24){//如果小时数大于等于24,则进入下一天,直接减去24小时,调用减时方法 //只要超过24,有几个减几个。 this.subHour((this.getHour()/24)*24); } //减 时/分/秒 的判断 if(this.getSecond()<0){//如果秒数小于0,则进行减1分加60秒操作,调用减分加秒方法 int min = this.getSecond()/-60; //这里判断需要几个整的分钟数 //这里判断减去的秒数是不是整的60秒,如果是则减去相对应的分钟数 if(this.getSecond()%-60 != 0){//如果余数不为0,则需要减去的分钟数要加1. min += 1; } this.subMinute(min); this.addSecond((min)*60);//减去了几个分钟数就加上多少个60秒 } if(this.getMinute()<0){//如果分钟数小于0,则进行减1时加60分操作,调用加分减时方法 int hou = this.getMinute()/-60; //这里判断需要几个整的小时数 //这里判断减去的分钟数数是不是整的60分,如果是则减去相对应的时数 if(this.getMinute()%-60 != 0){//如果余数不为0,则需要减去的时数要加1. hou += 1; } this.subHour(hou); this.addMinute(hou*60); } //由于-1/-24 = 1,所以这里改用for循环试试 //如果小时数<0,则时光倒回,加上整的24小时,调用加时方法。 for(;this.getHour()<0;){//只要小于0就为小时数进行+24的操作 this.addHour(24); } if(this.getHour()<0){ // 判断需要加几个24小时 int day = this.getHour()/-24;//如果小时数<0,则时光倒回,加上整的24小时,调用加时方法。 if(day%-24 != 0){ day +=1; } this.addHour((day)*24); } System.out.println(this.getHour()+"时"+this.getMinute()+"分"+this.getSecond()+"秒"); } //当时的一个思路,不一定对。可忽略 //加/减 时/分/秒 //加时/分/秒操作时,单个方法加会很麻烦,所以整体放到打印时/分/秒分方法里。 //以下每个方法只能加到上一级之后就不会再加,存在漏洞,所以不再使用。 //如:加秒的如果超过3600秒则分钟数就会超过60。所以不再进行下去 /* public void addSecond(int sec){ //先进行加秒操作 this.setSecond(this.getSecond()+sec); //如果大于60秒,就要进行加分操作。 //默认设置为加1分钟,然后判断是不是大于60秒,如果大于则加一分,加一分之后,秒数-60,然后继续判断 for(int min =1;this.getSecond()>=60;this.setSecond(this.getSecond() - 60)){ this.setMinute(this.getMinute()+min); } // if (this.getSecond()>=60){ // this.setSecond(this.getSecond() - 60); // } } public void addMinute(int min){ //进行加分操作 this.setMinute(this.getMinute()+min); //如果大于60分,就要进行加时操作。 //默认设置为加1时,然后判断是不是大于60分,如果大于则加一时,加一时之后,分数-60,然后继续判断 for(int hou =1;this.getMinute()>=60;this.setMinute(this.getMinute() - 60)){ this.setHour(this.getHour()+hou); } } public void addHour(int hou){ //进行加时操作 this.setHour(this.getMinute()+hou); //如果大于24时,就要进行加天操作。 //这里不让他大于24 if (this.getHour()>24){ this.setHour(this.getMinute()-24); } } */ public void addSecond(int sec){ this.setSecond(this.getSecond()+sec); } public void addMinute(int min){ this.setMinute(this.getMinute()+min); } public void addHour(int hou){ this.setHour(this.getHour()+hou); } public void subSecond(int sec){ this.setSecond(this.getSecond()-sec); } public void subMinute(int min){ this.setMinute(this.getMinute()-min); } public void subHour(int hou){ this.setHour(this.getHour()-hou); } }