Day11 JavaSE

48 阅读10分钟

今日重点 方法重写

1.方法重写

方法重写是在继承中提到的,java允许子类对从父类继承过来的方法进行重新实现

规则:1.子类方法必须和父类方法的方法名相同
    2.子类方法的参数列表必须和父类方法的参数列表相同
    3.子类方法的返回值必须和父类方法的返回值相同
    4.子类的访问权限修饰符和父类的访问权限修饰符相同,或者父类的访问权限修饰符大于子类访问权限修饰符

检查该方法是否重写:在重写方法上加入@override注解,来进行检查

//父类
package pojo;  
  
public class Parent {  
public String getName(){  
return "父类中的方法";  
}  
}
//子类
package pojo;  
  
public class Child extends Parent{  
@Override  
public String getName(){  
return "子类中的方法";  
}  
}
//测试类
package pojo;  
  
public class Test {  
public static void main(String[] args) {  
Child child=new Child();  
System.out.println(child.getName());  
}  
}

image.png

静态方法无法进行方法重写

package pojo;  
  
public class Parent {  
//父类静态方法
public static String getName(){  
return "父类中的方法";  
}  
}

//子类静态方法 image.png

因为被static修饰的方法在方法区里面只能被使用一次,你父类已经使用一次了,无法继承子类再继续使用.

2.方法重写之super关键字

super关键字的作用--在子类中重写之后想看看父类中调用的方法

在子类中,如果重写了父类的方法,但是还想看看你重写的这个父类方法是啥,可以通过super关键字进行实现.

//父类
package pojo;  
  
public class Parent {  
public void getName(){  
System.out.println("父类中的方法");  
}  
}

/子类
package pojo;  
  
public class Child extends Parent{  
@Override  
public void getName(){  
super.getName();  
System.out.println("子类中的方法");  
}  
}
//测试类
package pojo;  
  
public class Test {  
public static void main(String[] args) {  
Child child=new Child();  
child.getName();  
}  
}

代码执行结果演示: image.png

3.方法重写和方法重载的区别

最主要的区别:作用不同

方法重载是为了去解决同一功能之下的不同的解决办法,比如说我的登录功能,可以在微信登录,可以在qq登录,可以用电话登录,同一功能之下的不同解决方案.

方法重写:子类方法继承父类的方法,但是有的时候子类想放点自己的东西来满足自己的需求就会使用方法重写.

第二个区别:

方法重载:同一个类中,方法名相同参数列表不同

方法重写:发生在继承的时候,不同类,方法名相同,参数列表相同,返回值相同,访问修饰符相同 或者是子类的访问修饰符权限要不小于父类的访问修饰符权限

4.小节实战案例

//电脑类
package pojo3;  
  
public class Computer extends Product{  
public int cpu;  
  
public Computer(String name, String price, int cpu) {  
super(name, price);  
this.cpu = cpu;  
}  
  
public Computer() {  
  
}  
  
public int getCpu() {  
return cpu;  
}  
  
public void setCpu(int cpu) {  
this.cpu = cpu;  
}  
public void show(){  
super.show();  
System.out.println("cpu的数量是"+getCpu());  
}  
}


//手机类
package pojo3;  
  
public class Phone extends Product {  
public String color;  
public String storage;  
  
public Phone(String name, String price, String color, String storage) {  
super(name, price);  
this.color = color;  
this.storage = storage;  
}  
public Phone() {  
}  
  
public String getColor() {  
return color;  
}  
  
public void setColor(String color) {  
this.color = color;  
}  
  
public String getStorage() {  
return storage;  
}  
  
public void setStorage(String storage) {  
this.storage = storage;  
}  
@Override  
public void show(){  
super.show();  
System.out.println("手机颜色是:"+getColor()+"手机内存是"+getStorage());  
  
}  
}


//商品类
package pojo3;  
  
public class Product {  
public String name;  
public String price;  
//带参构造  
public Product(String name, String price) {  
this.name = name;  
this.price = price;  
}  
//无参构造  
public Product() {  
}  
//定义show方法用于显示对象的属性信息  
public void show(){  
System.out.print("商品名称\t"+getName()+"商品价格\t"+getPrice());  
  
}  
  
public String getName() {  
return name;  
}  
  
public void setName(String name) {  
this.name = name;  
}  
  
public String getPrice() {  
return price;  
}  
  
public void setPrice(String price) {  
this.price = price;  
}  
}

//测试类
package pojo3;  
  
public class Test01 {  
public static void main(String[] args) {  
Phone phone=new Phone();  
phone.setStorage("2");  
phone.setColor("red");  
phone.setName("苹果");  
phone.setPrice("1999");  
phone.show();  
  
}  
}

image.png

5.访问权限修饰符

四种访问权限修饰符

作用:来控制那些细节需要封装,那些细节需要暴露

作用范围:
1.private--只能在该类中进行访问
2.default--能在该类中进行访问,能在同一个包中进行访问
3.protected--能在该类中进行访问,能在同一个包中进行访问,能在不同包中的子类进行访问
4.public--只要是在这个项目中就可以进行访问

能修饰的东西:
1.能修饰类,属性,构造方法的是:default,public
2.能修饰属性,构造方法,方法的是 private,protected

5.封装常见面试题

1.在java中,继承关系允许子类和父类出现同名属性
2.子类和父类出现同名属性时候,实例化子类对象,会调用子类的属性(就近原则)如果子类有调用子类属性,如果子类没有调用父类属性
3.如果父类中的方法调用了属性的值,而子类重写了这个方法。实例化子类对象时输出的是子类属性值。因为子类重写了父类的方法,所以实例化子类后调用的就是子类的方法,子类方法操作的是子类的属性,所以最终输出是子类的属性值
4.如果子类继承了父类的属性,且在子类中存在同名属性。可以通过super关键字调用父类的属性。
super关键字代表的是父类对象,所有**能够被子类继承**的方法或属性都能通过super关键字调用。
无论是否出现同名方法或同名属性,都可以使用super关键字调用父类允许被继承的方法或属性。
可以使用this关键字调用子类自己的方法和属性(this可以省略)

6.小节实战案例

package pojo1;  
  
import java.util.Scanner;  
  
public class Menu {  
  
  
public void test() {  
int phonecount = 0;  
Phone[] phones = new Phone[50];  
Scanner sc = new Scanner(System.in);  
System.out.println("欢迎查看JD系统");  
while (true) {  
System.out.println("1.录入手机");  
System.out.println("2.查看手机");  
System.out.println("3.录入电脑");  
System.out.println("4.查看电脑");  
System.out.println("5.退出系统");  
int i = sc.nextInt();  
switch (i) {  
case 1:  
System.out.println("是否要录入手机商品");  
phonecount=add(sc,phones,phonecount);  
  
  
break;  
case 2:  
System.out.println("请查看手机");  
show(phones,phonecount);  
  
  
break;  
case 3:  
break;  
case 4:  
break;  
case 5:  
break;  
  
  
}  
  
}  
}  
  
public int add(Scanner sc, Phone[] phones, int phonecount) {  
String yn = sc.next();  
if (yn.equals("y")) {  
System.out.println("请录入手机名称");  
String phoneNames = sc.next();  
System.out.println("请录入手机价格");  
String phonePrice = sc.next();  
System.out.println("请录入手机颜色");  
String phoneColor = sc.next();  
System.out.println("请录入手机卡");  
String phoneCard = sc.next();  
Phone p = new Phone();  
  
p.setName(phoneNames);  
p.setPrice(phonePrice);  
p.setColor(phoneColor);  
  
p.setCard(phoneCard);  
phones[phonecount] = p;  
phonecount++;  
  
  
}  
return phonecount;  
}  7.
public void show(Phone[]phones,int phonecount){  
System.out.println("商品名称\t商品价格\t商品颜色\t商品手机卡");  
for(int x=0;x<phonecount;x++){  
System.out.println(phones[x].getName()+phones[x].getPrice()+phones[x].getColor()+phones[x].getCard());  
  
}  
}  
}

image.png

7. 枚举.

枚举中定义的是常量

语法:
public enum 枚举类名字{

}

枚举也是一个类

8.final关键字

final可以修饰变量,方法,类

修饰变量 被final修饰的属性(成员变量和局部变量)称为常量,是不可改变的。一旦赋了初值,就不能被重新赋值。

修饰非静态属性

final修饰的非静态属性仅能赋值唯一一次。且在使用前必须赋予初值。

* final修饰的非静态属性的赋值机会有三个,分别是:

* 1. 定义属性并初始化

* 2. 构造方法赋值

* 3. 成员代码块赋值

* 三个赋值机会任选其一,且只能选择一种方式



package pojo4;  
  
public class Test {  
private final String name;  
private final int age=20;  
  
public Test() {  
this.name="默认值";  
}  
{  
//成员代码块赋值  
}  
  
public Test(String name) {  
this.name = name;  
}  
}

修饰静态属性 要求此属性必须在定义后,使用前赋予初值。仅能赋值唯一一次,有两个赋值机会,任选其一。

* final修饰的静态属性仅能赋值唯一一次。且在使用前必须赋予初值。

* final修饰的静态属性的赋值机会有两个,分别是:

* 1. 定义属性并初始化

* 2. 静态代码块赋值

* 两个赋值机会任选其一,且只能选择一种方式。

package pojo4;  
  
public class Test01 {  
private static final String name;  
private static final int age=20;  
static {  
name="静态代码块赋值";  
}  
}

修饰局部变量

* final修饰的局部变量仅能赋值唯一一次。且在使用前必须赋予初值。

* final修饰的局部变量的赋值机会有两个,分别是:

* 1. 定义属性并初始化

* 2. 使用前赋值

* 两个赋值机会任选其一,且只能选择一种方式。


package pojo4;  
  
public class Test02 {  
public void test(final String remark){  
final String name="定义时初始化赋值";  
final int i;  
i=10;  
System.out.println(i);  
  
}  
}

修饰方法 被final修饰方法不可被子类重写。但是可以被重载!

image.png

修饰的类

修饰的类不能被继承。在JDK中很多类都是final修饰的。如:String、八大基本数据类型封装类等。如果把Java

中所有的类型的继承关系看作是一颗树,那么Object就是树的根,因为所有的类型的祖先类型一定是Object,

那么final修饰的类就是叶子类,代表不会再有枝杈出现。

image.png

私有的final方法 当父类中final修饰方法的访问权限修饰符是private时,子类是不可以访问这个方法的,所以也就不构成重写条件。这个时候在子类中提供一个和父类相同的方法时是允许的。

final修饰引用类型变量时 对于引用数据类型赋值的语法:

类型 对象名 = new 构造方法();

上述流程中,是给引用类型的变量"对象名"赋值。对于内存来说:是在堆中开辟了一块空间,创建对象,并把

此空间的地址引用赋给变量。

如果使用final修饰:变量存储堆中开辟的内存空间的引用地址,变量不允许再次赋值,代表变量中存储的堆空

间地址不可改变,换言之,不能重新创建对象并赋值给final变量。

final 类型 对象= new 类型();

不能修改的是变量的值,也就是引用地址:对象 = new 类型();

允许修改对象的属性值。如:对象.属性名 = 新值;

被final东西应该存在jvm的哪里 image.png

9.抽象类和抽象方法

抽象abstract

1.存在的意义:就是让子类强制重写父类中的方法 2.抽象方法可以写在抽象类中,普通类不能写抽象方法 image.png 3.抽象方法可以被重写,可以重载

被重载场景 image.png 被重写场景 image.png 4.abstract可以修饰类和方法

抽象类 和 抽象方法

  • 抽象的关键字 是 abstract
  • 在父类中 使用 abstract 修饰方法的时候 要求子类必须重写这个方法
  • 所以, 父类中就没有必要给方法准备方法体了
  • 注意:
  • 抽象方法 只能写在抽象类中
  • 抽象类 可以被继承
  • abstract 不可以和final一起使用 image.png 因为abstract之后子类必须重写,但是被final修饰的子类不可以重写,矛盾.
  • 抽象类中的抽象方法 子类不能调用 是让子类重写的 不是让子类调用的
  • 抽象类中的其他能调用的方法 都可以正常调用
  • 抽象类可以向正常类一样书写代码 就是多出了一个抽象方法
  • 但是 抽象类 不能 像 普通类一样 被直接实例化 image.png

原因:因为抽象类其实就是个特殊的接口,里面有没有实现的方法,你实例化的话没有可以调用的方法 父类想要实现实例化,必须要用匿名内部类,去实现父类里面的所有方法,可以实现父类的实例化 image.png