第三次pta大作业

OO第三次博客作业

一、PTA三次大作业题目集的前言

对于第六次,第七次,第八次pta大作业,难度不是很难,主要是考察对输入数据的处理、应用和储存。

1.第六次题目集

7-1 电信计费系列1-座机计费:

实现一个简单的电信计费程序:假设南昌市电信分公司针对市内座机用户采用的计费方式,是对数据进行识别,储存,处理,计算,最后在输出电话号码和花费以及余额;

7-2 多态测试:

定义容器Container接口。模拟实现一个容器类层次结构,并进行接口的实现、抽象方法重写和多态机制测试。各容器类实现求表面积、体积的方法。运用抽象方法来进行对输入数据的处理,在进行运算。

2.第七次题目集

7-1 电信计费系列2-手机+座机计费:

实现南昌市电信分公司的计费程序,假设该公司针对手机和座机用户分别采取了两种计费方案,分别如下:对数据进行识别,储存,处理,计算,最后在输出电话号码和花费以及余额

7-2 sdut-Collection-sort--C~K的班级(II):

经过不懈的努力,C~K终于当上了班主任。

现在他要统计班里学生的名单,但是C~K在教务系统中导出班级名单时出了问题,发现会有同学的信息重复,现在他想把重复的同学信息删掉,只保留一个,
但是工作量太大了,所以找到了会编程的你,你能帮他解决这个问题吗?

排序:

String p=null;
for(int i=0;i<s;i++) {
for(int k=i+1;k<s;k++) {
if(q[i].compareTo(q[k])>0){
p=q[i];
q[i]=q[k];
q[k]=p;
}
}
}

7-3 阅读程序,按照题目需求修改程序:

功能需求:
使用集合存储3个员工的信息(有序);
通过迭代器依次找出所有的员工。

 

3.第八次题目集

7-1 电信计费系列3-短信计费:

实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:

7-2 编写一个类Shop(商店)、内部类InnerCoupons(内部购物券):

编写一个类Shop(商店),该类中有一个成员内部类InnerCoupons(内部购物券),可以用于购买该商店的牛奶(假设每箱牛奶售价为50元)。要求如下:

7-3 动物发声模拟器(多态):

设计一个动物发生模拟器,用于模拟不同动物的叫声。比如狮吼、虎啸、狗旺旺、猫喵喵……。

二、设计与分析

1.7-1 电信计费系列1-座机计费

实现一个简单的电信计费程序:
假设南昌市电信分公司针对市内座机用户采用的计费方式:
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
南昌市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。

输入格式:

输入信息包括两种类型
1、逐行输入南昌市用户开户的信息,每行一个用户,
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐)
例如:u-079186300001 0
座机号码除区号外由是7-8位数字组成。
本题只考虑计费类型0-座机计费,电信系列2、3题会逐步增加计费类型。
2、逐行输入本月某些用户的通讯信息,通讯信息格式:
座机呼叫座机:t-主叫号码 接听号码 起始时间 结束时间
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四项内容之间以一个英文空格分隔,
时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。
以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
注意:
本题非法输入只做格式非法的判断,不做内容是否合理的判断(时间除外,否则无法计算),比如:
1、输入的所有通讯信息均认为是同一个月的通讯信息,不做日期是否在同一个月还是多个月的判定,直接将通讯费用累加,因此月租只计算一次。
2、记录中如果同一电话号码的多条通话记录时间出现重合,这种情况也不做判断,直接 计算每条记录的费用并累加。
3、用户区号不为南昌市的区号也作为正常用户处理。

输出格式:

根据输入的详细通讯信息,计算所有已开户的用户的当月费用(精确到小数点后2位,
单位元)。假设每个用户初始余额是100元。
每条通讯信息单独计费后累加,不是将所有时间累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。

错误处理:
输入数据中出现的不符合格式要求的行一律忽略。

建议类图:
参见图1、2、3,可根据理解自行调整:

image.png

                                    图1
图1中User是用户类,包括属性:
userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。

ChargeMode是计费方式的抽象类:
chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。
getMonthlyRent()方法用于返回月租(monthlyRent)。

UserRecords是用户记录类,保存用户各种通话、短信的记录,    
各种计费规则将使用其中的部分或者全部记录。
其属性从上到下依次是:
市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、
市内接听电话、省内(不含市内)接听电话、省外接听电话的记录
以及发送短信、接收短信的记录。
 

image.png

                                     图2
图2中CommunicationRecord是抽象的通讯记录类:
包含callingNumber拨打号码、answerNumber接听号码两个属性。
CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。

CallRecord(通话记录类)包含属性:
通话的起始、结束时间以及
拨号地点的区号(callingAddressAreaCode)、接听地点的区号(answerAddressAreaCode)。
区号用于记录在哪个地点拨打和接听的电话。座机无法移动,就是本机区号,如果是手机号,则会有差异。
 

image.png

                                        图3
图3是计费规则的相关类,这些类的核心方法是:
calCost(ArrayList<CallRecord> callRecords)。
该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。
输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。

LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是
座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。    
(提示:可以从UserRecords类中获取各种类型的callRecords)。
 

后续扩展说明:
后续题目集将增加手机用户,手机用户的计费方式中除了与座机计费类似的主叫通话费之外,还包含市外接听电话的漫游费以及发短信的费用。在本题的设计时可统一考虑。
通话记录中,手机需要额外记录拨打/接听的地点的区号,比如:
座机打手机:t-主叫号码 接听号码 接听地点区号 起始时间 结束时间
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
手机互打:t-主叫号码 拨号地点 接听号码 接听地点区号 起始时间 结束时间
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11
短信的格式:m-主叫号码,接收号码,短信内容
m-18907910010 13305862264 welcome to jiangxi
m-13305862264 18907910010 thank you

部分参考测试用例: 以下内容绿色部分为输入,紧接其后的黑色部分为输出。

u-079186300001 0

t-079186300001 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:25

end

079186300001 3.0 77.0

u-079186300001 0

t-079186300001 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:26

end

079186300001 3.6 76.4

u-079186300001 0

u-079186300002 0

t-079186300001 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:25

t-079186300002 058686330022 2022.1.3 11:00:25 2022.1.3 11:05:25

t-079186300001 079186300001 2022.1.3 12:00:25 2022.1.3 12:05:25

end

079186300001 3.5 76.5

079186300002 3.0 77.0

u-079186300002 0

u-079186300001 0

t-079186300001 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:25 t-079186300002 058686330022 2022.1.3 11:00:25 2022.1.3 11:05:25

t-079186300001 079186300001 2022.1.3 12:00:25 2022.1.3 12:05:25 end 079186300001 3.5 76.5 079186300002 3.0 77.0

u-079186300002 0

u-079186300001 0

t-079186300001 079286300002 2022.1.3 10:00:25 2022.1.3 10:05:25 end 079186300001 1.5 78.5 079186300002 0.0 80.0 u-079186300002 0

u-079186300001 0

t-079186300001 079286300002 2022.1.3 10:00:25 2022.1.3 10:05:25

t-079186300001 079186300003 2022.1.3 10:00:25 2022.1.3 10:05:25

end

079186300001 2.0 78.0

079186300002 0.0 80.0

u-079186300002 0

u-079186300001 0

t-079186300001 079186300002 2022.1.3 22:00:25 2022.1.3 22:05:32 t-079186300001 079186300003 2022.1.3 10:00:25 2022.1.3 10:05:25

end

079186300001 1.1 78.9

079186300002 0.0 80.0

u-079186300001 0

t-079186300001 079286330022 2022.1.3 12:50:00 2022.1.3 13:05:00 22

rr

end

079186300001 4.5 75.

2.7-2 多态测试

定义容器Container接口。模拟实现一个容器类层次结构,并进行接口的实现、抽象方法重写和多态机制测试。各容器类实现求表面积、体积的方法。

  1. 定义接口Container:
    属性:
    public static final double pi=3.1415926;
    抽象方法:
    public abstract double area();
    public abstract double volume();
    static double sumofArea(Container c[]);
    static double sumofVolume(Container c[]);
    其中两个静态方法分别计算返回容器数组中所有对象的面积之和、周长之和;
  2. 定义Cube类、Cylinder类均实现自Container接口。
    Cube类(属性:边长double类型)、Cylinder类(属性:底圆半径、高,double类型)。

输入格式:

第一行n表示对象个数,对象类型用cube、cylinder区分,cube表示立方体对象,后面输入边长,输入cylinder表示圆柱体对象,后面是底圆半径、高。

输出格式:

分别输出所有容器对象的表面积之和、体积之和,结果保留小数点后2位。

import java.text.DecimalFormat;
import java.util.Scanner;


public class Main {
    public static void main(String[] args) {    
        String str;
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        Container c[] = new Container[n];
        for(int i=0;i<n;i++) {
              
              str=sc.next();
            if(str.equals("cube")){
             
             c[i]=new Cube(sc.nextDouble());
            }
            else if(str.equals("cylinder")) {
                double q=sc.nextDouble();
                double p=sc.nextDouble();
                c[i]=new Cylinder(q,p);    
            }
        }
        System.out.println(Container.sumofArea(c)); 
        System.out.println(Container.sumofVolume(c));
    }
}
interface Container{
    public static final double pi=3.1415926;
    
    
    public abstract double area();
    public abstract double volume();
    static double sumofArea(Container c[]) {

         double s=0;
         
        for(Container j:c) {
            s+=j.area();
        }
        DecimalFormat d = new DecimalFormat("#.00");
        Double output = Double.valueOf(d.format(s));
        return output;
    }
    static double sumofVolume(Container c[]) {
        
        double f=0;
        
        for(Container d:c) {
            f+=d.volume();
        }
        DecimalFormat d = new DecimalFormat("#.00");
        Double output = Double.valueOf(d.format(f));
        return output;
    }
}
class Cube implements Container{
    
    private double q;

    Cube(double q) {
        this.q=q;
    }


    public double area() {
    double a=q*q*6;
        return a;
    }


    public double volume() {
        double v=q*q*q;
        return v;
    }

}
class Cylinder implements Container{
    
    private double q;
    private double p;
    Cylinder(double q, double p) {
        this.q=q;
        this.p=p;
    }

    public double area() {
         double a=pi*q*q*2+2*pi*q*p;
        return a;
    }

    public double volume() {
        double v=pi*q*q*p;
        return v;
    }
}

输入样例:

在这里给出一组输入。例如:

4
cube
15.7
cylinder
23.5 100
cube
46.8
cylinder
17.5 200
 

输出样例:

在这里给出相应的输出。例如:

56771.13
472290.12

3.7.1 电信计费系列2-手机+座机计费

实现南昌市电信分公司的计费程序,假设该公司针对手机和座机用户分别采取了两种计费方案,分别如下:
1、针对市内座机用户采用的计费方式(与电信计费系列1内容相同):
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
假设本市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。
2、针对手机用户采用实时计费方式:
月租15元,市内省内接电话均免费,市内拨打市内电话0.1元/分钟,市内拨打省内电话0.2元/分钟,市内拨打省外电话0.3元/分钟,省内漫游打电话0.3元/分钟,省外漫游接听0.3元/分钟,省外漫游拨打0.6元/分钟;
注:被叫电话属于市内、省内还是国内由被叫电话的接听地点区号决定,比如以下案例中,南昌市手机用户13307912264在区号为020的广州接听了电话,主叫号码应被计算为拨打了一个省外长途,同时,手机用户13307912264也要被计算省外接听漫游费:
u-13307912264 1
t-079186330022 13307912264 020 2022.1.3 10:00:25 2022.1.3 10:05:11

输入:
输入信息包括两种类型
1、逐行输入南昌市用户开户的信息,每行一个用户,含手机和座机用户
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐)
例如:u-079186300001 0
座机号码由区号和电话号码拼接而成,电话号码包含7-8位数字,区号最高位是0。
手机号码由11位数字构成,最高位是1。
本题在电信计费系列1基础上增加类型1-手机实时计费。
手机设置0或者座机设置成1,此种错误可不做判断。
2、逐行输入本月某些用户的通讯信息,通讯信息格式:
座机呼叫座机:t-主叫号码 接听号码 起始时间 结束时间
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四项内容之间以一个英文空格分隔,
时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。
输入格式增加手机接打电话以及收发短信的格式,手机接打电话的信息除了号码之外需要额外记录拨打/接听的地点的区号,比如:
座机打手机:
t-主叫号码 接听号码 接听地点区号 起始时间 结束时间
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
手机互打:
t-主叫号码 拨号地点 接听号码 接听地点区号 起始时间 结束时间
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11

注意:以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。

输出:
根据输入的详细通讯信息,计算所有已开户的用户的当月费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条通讯、短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。

本题只做格式的错误判断,无需做内容上不合理的判断,比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码等,此类情况都当成正确的输入计算。但时间的输入必须符合要求,比如不能输入2022.13.61 28:72:65。
 

建议类图:
参见图1、2、3:

image.png
图1

图1中User是用户类,包括属性:
userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。
ChargeMode是计费方式的抽象类:
chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。
getMonthlyRent()方法用于返回月租(monthlyRent)。
UserRecords是用户记录类,保存用户各种通话、短信的记录,    
各种计费规则将使用其中的部分或者全部记录。
其属性从上到下依次是:
市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、
市内接听电话、省内(不含市内)接听电话、省外接听电话的记录
以及发送短信、接收短信的记录。
 

image.png

图2

图2中CommunicationRecord是抽象的通讯记录类:
包含callingNumber拨打号码、answerNumber接听号码两个属性。
CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。CallRecord(通话记录类)包含属性:
通话的起始、结束时间以及
拨号地点的区号(callingAddressAreaCode)、接听地点的区号(answerAddressAreaCode)。
区号用于记录在哪个地点拨打和接听的电话。座机无法移动,就是本机区号,如果是手机号,则会有差异。
 

image.png
图3

图3是计费规则的相关类,这些类的核心方法是:
calCost(ArrayList<CallRecord> callRecords)。
该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。
输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。
SendMessageRule是发送短信的计费规则类,用于计算发送短信的费用。
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。    
 

(提示:可以从UserRecords类中获取各种类型的callRecords)。
注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。

import java.util.ArrayList;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.Scanner;

public class Main {
    public static void main(String[] args)  {
        SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
        ArrayList<User> Users=new ArrayList<User>();
        Scanner sc=new Scanner(System.in);
        String mq=sc.nextLine();
        mq=mq.substring(2);
        String[] s=mq.split(" ");
    
        
        User user;
        while(mq.charAt(0)=='u') {
            
            if((mq.length()==14||mq.length()==13)) {
                user=new User();
                user.number=s[0];
                Users.add(user);
                
            }
            else if((mq.length()==14||mq.length()==13)) {
                
                user=new User();
                user.number=s[0];
                Users.add(user);
            
            }
            mq=sc.nextLine();
            s=mq.split(" ");
        }
        while(mq.charAt(0)=='t') {
            int m=0;
            for(int i=0;i<mq.length();i++) {
                if(mq.charAt(i)==' ') {
                    m++;
                }
            }
            if(m==7) {
                
            }
            mq=mq.substring(2);
            if(mq.length()==13||mq.length()==1) {
                user=new User();
                user.number=s[0];
                Users.add(user);
            }
        }
        mq=sc.nextLine();
        s=mq.split(" ");
    }
}
class User{
    String number;
    double balance=100;
//    UserRecords chargeMode;
    double buy=0;
    ArrayList<conversation> All = new  ArrayList<conversation>();
    
}
class UserRecords {
    String callnumber;
    String getnumber;
}

class conversation extends UserRecords {
    Date time1;
    Date time2;
    String callplace;
    String getplace;
}
class format{
    public static boolean iszuoji(String zuoji) {
        return true;
    }
    public static boolean isshouji(String phone) {
        return true;
    }
    public static SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
    
    public static boolean time(String time) {
        try {
            format.parse(time);
            return true;
        }catch(Exception e){
            return false;
        }
    }
}

u-13811111111 1

u-13811111110 1

u-13811111111 1

t-13811111111 0791 13811111110 020 2022.1.3 08:00:00 2022.1.3 08:09:20

end

13811111110 3.0 82.0

13811111111 3.0 82.0

u-079186300001 0

u-13986300001 1

t-18907910010 0791 13986300001 0371 2022.1.3 10:00:25 2022.1.3 10:05:11

end

079186300001 0.0 80.0

13986300001 1.5 83.5

u-079186300001 0

u-13986300001 1

t-079186300001 13986300001 0371 2022.1.3 10:00:25 2022.1.3 10:05:11

end

079186300001 3.0 77.0

13986300001 1.5 83.5

u-079186300001 0

u-13986300001 1

t-13986300001 0371 079186300001 2022.1.3 10:00:25 2022.1.3 10:05:11

end

079186300001 0.0 80.0

13986300001 3.0 82.0

u-079186300001 0

u-13986300001 1

t-13986300001 0371 079186300001 2022.1.3 23:50:25 2022.1.4 00:05:11

end

079186300001 0.0 80.0

13986300001 9.0 76.0

u-13986300001 1

t-13986300001 0791 079186300001 2022.12.31 23:50:25 2023.1.2 00:05:11

end

13986300001 145.5 -60.5

u-13986300001 1

t-13986300001 0791 079186300001 2022.12.31 23:50:25 2023.1.1 00:05:11

t-13986300001 0799 079186300001 2022.12.31 23:50:25 2023.1.1 00:05:11

t-13986300001 0391 079186300001 2022.12.31 23:50:25 2023.1.1 00:05:11

end

13986300001 15.0 70.0

u-13986300001 1

u-079182200000 0

u-079182200000 0

u-13986300066 1

t-079182200000 13986300066 0730 2022.8.31 23:50:25 2022.9.1 00:00:11 ss

t-079182200000 13986300066 0791 2022.8.31 23:50:25 2022.9.1 00:00:11

t-079182200000 0730000000 2022.8.31 23:50:25 2022.9.1 00:00:11

t-13986300066 0730 13986300001 0731 2022.8.31 23:50:25 2022.9.1 00:00:11

end

079182200000 13.0 67.0

13986300001 3.0 82.0

13986300066 9.0 76.

4.7-2 sdut-Collection-sort--C~K的班级(II)

经过不懈的努力,C~K终于当上了班主任。

现在他要统计班里学生的名单,但是C~K在教务系统中导出班级名单时出了问题,发现会有同学的信息重复,现在他想把重复的同学信息删掉,只保留一个,
但是工作量太大了,所以找到了会编程的你,你能帮他解决这个问题吗?

输入格式:

第一行输入一个N,代表C~K导出的名单共有N行(N<100000).

接下来的N行,每一行包括一个同学的信息,学号 姓名 年龄 性别。

输出格式:

第一行输出一个n,代表删除重复名字后C~K的班级共有几人。

接下来的n行,输出每一个同学的信息,输出按照学号从小到大的顺序。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        String str;
        Scanner in = new Scanner(System.in);
        int s = in.nextInt();
        in.nextLine();
        String[] q = new String[s];
        for(int i=0;i<s;i++) { 
              str=in.nextLine();
            q[i]=str;
        }
        for(int i=0;i<s-1;i++) {
            for(int k=i+1;k<s;k++) 
                {
                    if(q[i].equals(q[k])) 
                {
                        for(int j=k;j<s-1;j++)
                            q[j]=q[j+1];
                        s--;
                        k--;
                        
                }
                
            }
        }
        
        System.out.println(s);
        String p=null;
        for(int i=0;i<s;i++) {
            for(int k=i+1;k<s;k++) {
             if(q[i].compareTo(q[k])>0){
                 p=q[i];
                 q[i]=q[k];
                 q[k]=p;
             }
            }
        }
        for(int i=0;i<s;i++) {
            System.out.println(q[i]);
        }
    }
}

输入样例:

6
0001 MeiK 20 M
0001 MeiK 20 M
0002 sdk2 21 M
0002 sdk2 21 M
0002 sdk2 21 M
0000 blf2 22 F
 

输出样例:

3
0000 blf2 22 F
0001 MeiK 20 M
0002 sdk2 21 M

5.7-3 阅读程序,按照题目需求修改程序

功能需求:
      使用集合存储3个员工的信息(有序);
      通过迭代器依次找出所有的员工。
 

提示:学生复制以下代码到编程区,并按需求进行调试修改。

// 1、导入相关包

//定义员工类
class Employee {

    private String name;
    private int age;

    public Employee() {
        super();
    }

    public Employee(String name, int age) {
        super();
        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 class Main {

    public static void main(String[] args) {
                // 1、创建有序集合对象
                Collection c ;

      // 创建3个员工元素对象
        for (int i = 0; i < 3; i++) {
            Scanner sc = new Scanner(System.in);
            String employeeName = sc.nextLine();
            int employeeAge = sc.nextInt();
            
            Employee employee = new Employee(employeeName, employeeAge);
            c.add(employee);
        }            
                
                
                
                // 2、创建迭代器遍历集合
                Iterator it;
                
                //3、遍历
                while (it.hasnext) {
                    
                    //4、集合中对象未知,向下转型
                    Employee e =  it.next();
                    
                    System.out.println(e.getName() + "---" + e.getAge());
                }
    }

}
//1、导入相关包
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Collection;
import java.util.Iterator;

//定义员工类
class Employee {

    private String name;
    private int age;

    public Employee() {
        super();
    }

    public Employee(String name, int age) {
        super();
        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 class Main {

    public static void main(String[] args) {
                // 1、创建有序集合对象
                Collection c = new ArrayList(); 
                Scanner sc = new Scanner(System.in);
                 String employeeName = sc.nextLine();
                int employeeAge = sc.nextInt();
            
   // 创建3个员工元素对象
        for (int i = 0; i < 3; i++) {
                
            Employee employee = new Employee(employeeName, employeeAge);
            c.add(employee);
        }            
                
                
                
                // 2、创建迭代器遍历集合
                Iterator it=c.iterator();
                
                //3、遍历
                while (it.hasNext()) {
                    
                    //4、集合中对象未知,向下转型
                    Employee e = (Employee)it.next();
                    
                    System.out.println(e.getName() + "---" + e.getAge());
                }
    }
}    

输入样例:

在这里给出一组输入。例如:

zs 
10
ls
20
ww 
30
 

输出样例:

在这里给出相应的输出。例如:

zs---10
ls---20
ww---30
 

6.7-1 电信计费系列3-短信计费

实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:
1、接收短信免费,发送短信0.1元/条,超过3条0.2元/条,超过5条0.3元/条。
2、如果一次发送短信的字符数量超过10个,按每10个字符一条短信进行计算。

输入:
输入信息包括两种类型
1、逐行输入南昌市手机用户开户的信息,每行一个用户。
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐 3-手机短信计费)
例如:u-13305862264 3
座机号码由区号和电话号码拼接而成,电话号码包含7-8位数字,区号最高位是0。
手机号码由11位数字构成,最高位是1。
本题只针对类型3-手机短信计费。
2、逐行输入本月某些用户的短信信息,短信的格式:
m-主叫号码,接收号码,短信内容 (短信内容只能由数字、字母、空格、英文逗号、英文句号组成)
m-18907910010 13305862264 welcome to jiangxi.
m-13305862264 18907910010 thank you.

注意:以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
输出:
根据输入的详细短信信息,计算所有已开户的用户的当月短信费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
本题只做格式的错误判断,无需做内容上不合理的判断,比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码、自己给自己打电话等,此类情况都当成正确的输入计算。但时间的输入必须符合要求,比如不能输入2022.13.61 28:72:65。

本题只考虑短信计费,不考虑通信费用以及月租费。

建议类图:
参见图1、2、3:

image.png

图1

图1中User是用户类,包括属性:
userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。
ChargeMode是计费方式的抽象类:
chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。
getMonthlyRent()方法用于返回月租(monthlyRent)。    
UserRecords是用户记录类,保存用户各种通话、短信的记录,    
各种计费规则将使用其中的部分或者全部记录。
其属性从上到下依次是:
市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、
市内接听电话、省内(不含市内)接听电话、省外接听电话的记录
以及发送短信、接收短信的记录。
 

image.png

图2

    图2中CommunicationRecord是抽象的通讯记录类:
包含callingNumber拨打号码、answerNumber接听号码两个属性。
CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。
 

image.png

图3
图3是计费规则的相关类,这些类的核心方法是:
calCost(ArrayList callRecords)。
该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。
输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。
SendMessageRule是发送短信的计费规则类,用于计算发送短信的费用。
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。

(提示:可以从UserRecords类中获取各种类型的callRecords)。
 

注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。

import java.util.ArrayList;
import java.util.Scanner;
import java.text.DecimalFormat;
import java.util.Comparator;

public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        String mq=sc.nextLine();
        ArrayList<User> Users=new ArrayList<User>();
        DecimalFormat df = new DecimalFormat("0.00");
        User user;
        Xiaoxi xiaoxi;
        String nr;
        String hm2;
        while(!mq.equals("end")) {
            
        if(mq.matches("u-1[0-9]{10} 3")) {
            user=new User();
            user.number=mq.substring(2,13);
            Users.add(user);
            }
        else if(mq.matches("m-1[0-9]{10} 1[0-9]{10} [a-z A-Z 0-9,.]+")) {
                hm2=mq.substring(2,13);
                for(User xd: Users) {
                    if(hm2.equals(xd.number)) {
                        xiaoxi=new Xiaoxi();
                        xiaoxi.number1=mq.substring(2,13);
                        xiaoxi.number2=mq.substring(14,25);
                        nr=mq.substring(26);
                        xiaoxi.isneirong=nr;
                        if(Xiaoxi.isduanxin(nr)) {
                            for(User a:Users) {
                                if(a.number.equals(xiaoxi.number1))
                                    a.All.add(xiaoxi);
                            }
                        }
                    }
             }
                
                
           }
            else
                {}
            mq=sc.nextLine();
         }
        int sum=0;
        for(User a:Users) {
            for(Xiaoxi b:a.All) {
                double n1=b.isneirong.length()/10.0;
                int n2=(int) n1;
                if(n1-n2>0)    n2++;
                    sum+=n2;
            }
            if(sum>5)
                a.buy+=0.7+(sum-5)*0.3;
            else if(sum>3)
                a.buy+=0.3+(sum-3)*0.2;
            else
                a.buy+=sum*0.1;
            a.balance-=a.buy;
            
            sum=0;
        }
        Users.sort(new Sort_length());
        for(User a:Users) {
            System.out.println(a.number+" "+Double.valueOf(df.format(a.buy))+" "+Double.valueOf(df.format(a.balance)));
        }
    }
}

class Sort_length implements Comparator<User>{
    public int compare(User a,User b) {
        return a.number.compareTo(b.number);
    }
}

class Number{
    public static boolean isdianhua(String haoma) {
        if(haoma.matches("u-1[0-9]{10} 3")) {
            return true;
        }
        return false;
    }
    
}
class Xiaoxi{
    public String isneirong;
    String number1;
    String number2;
    
    public static boolean isduanxin(String xinxi) {
    if(xinxi.matches("[0-9 a-z A-Z,.]+")) {
        return true;
    }
    return false;
    }
}
class User{
    String number;
    double balance=100;
    double buy=0;
    ArrayList<Xiaoxi> All = new  ArrayList<Xiaoxi>();
    
}

输入样例:

在这里给出一组输入。例如:

u-18907910010 3
m-18907910010 13305862264 aaaaaaaaaaaaaaaaaaaaaaa
end
 

输出样例:

在这里给出相应的输出。例如:

18907910010 0.3 99.7
 
### 输入样例1:
 

在这里给出一组输入。例如:

u-18907910010 3
m-18907910010 13305862264 aaaaaaaaaaaa
m-18907910010 13305862264 aaaaaaa.
m-18907910010 13305862264 bb,bbbb
end
 

输出样例1:

在这里给出相应的输出。例如:

18907910010 0.5 99.5

7.7-2 编写一个类Shop(商店)、内部类InnerCoupons(内部购物券) 

编写一个类Shop(商店),该类中有一个成员内部类InnerCoupons(内部购物券),可以用于购买该商店的牛奶(假设每箱牛奶售价为50元)。要求如下:
(1)Shop类中有私有属性milkCount(牛奶的箱数,int类型)、公有的成员方法setMilkCount( )getMilkCount( )分别用于设置和获取牛奶的箱数。
(2)成员内部类InnerCoupons,有公有属性value(面值,int类型),一个带参数的构造方法可以设定购物券的面值value,一个公有的成员方法buy( )要求输出使用了面值为多少的购物券进行支付,同时使商店牛奶的箱数减少value/50。
(3)Shop类中还有成员变量coupons50(面值为50元的内部购物券,类型为InnerCoupons)、coupons100(面值为100元的内部购物券,类型为InnerCoupons)。
(4)在Shop类的构造方法中,调用内部类InnerCoupons的带参数的构造方法分别创建上面的购物券coupons50、coupons100。


在测试类Main中,创建一个Shop类的对象myshop,从键盘输入一个整数(大于或等于3),将其设置为牛奶的箱数。假定有顾客分别使用了该商店面值为50的购物券、面值为100的购物券各消费一次,分别输出消费后商店剩下的牛奶箱数。

输入格式:

输入一个大于或等于3的整数。

输出格式:

使用了面值为50的购物券进行支付
牛奶还剩XX箱
使用了面值为100的购物券进行支付
牛奶还剩XX箱

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        Shop myshop=new Shop(sc.nextInt());
        Shop.InnerCoupons coupons50=myshop.new InnerCoupons(50);
        Shop.InnerCoupons coupons100=myshop.new InnerCoupons(100);
        coupons50.buy();
        coupons100.buy();
    }
}
class Shop{
    static int milkCount;
    InnerCoupons coupons50;
    InnerCoupons coupons100;
    public Shop(int milkCount) {
        this.milkCount=milkCount;
    }
    
    public void setMilkCount(int milkCount) {
        this.milkCount=milkCount;
    }
    public int getMilkCount() {
        return milkCount;
    }
    public class InnerCoupons{
        public int value;
        public InnerCoupons(int value){
            this.value=value;
        }
        
        public void buy(){
            Shop.this.milkCount=Shop.this.milkCount-value/50;
            System.out.println("使用了面值为"+value+"的购物券进行支付");
            System.out.println("牛奶还剩"+Shop.this.milkCount+"");
        }
    }
}

输入样例:

在这里给出一组输入。例如:

5
 

输出样例:

在这里给出相应的输出。例如:

使用了面值为50的购物券进行支付
牛奶还剩4箱
使用了面值为100的购物券进行支付
牛奶还剩2箱

8.7-3 动物发声模拟器(多态)

设计一个动物发生模拟器,用于模拟不同动物的叫声。比如狮吼、虎啸、狗旺旺、猫喵喵……。
定义抽象类Animal,包含两个抽象方法:获取动物类别getAnimalClass()、动物叫shout();
然后基于抽象类Animal定义狗类Dog、猫类Cat和山羊Goat,用getAnimalClass()方法返回不同的动物类别(比如猫,狗,山羊),用shout()方法分别输出不同的叫声(比如喵喵、汪汪、咩咩)。
最后编写AnimalShoutTest类测试,输出:
猫的叫声:喵喵
狗的叫声:汪汪
山羊的叫声:咩咩

其中,在AnimalShoutTestMain类中,用speak(Animal animal){}方法输出动物animal的叫声,在main()方法中调用speak()方法,分别输出猫、狗和山羊对象的叫声。

请在下面的【】处添加代码。

//动物发生模拟器.  请在下面的【】处添加代码。
public class AnimalShoutTest2 {
    public static void main(String[] args) {        
         Cat cat = new Cat();
         Dog dog = new Dog();        
        Goat goat = new Goat();
         speak(cat);
         speak(dog);
         speak(goat);
    }
    //定义静态方法speak()
    【】

}

//定义抽象类Animal
【】class Animal{
    【】
}
//基于Animal类,定义猫类Cat,并重写两个抽象方法
class Cat 【】{
    【】    
    【】
}
//基于Animal类,定义狗类Dog,并重写两个抽象方法
class Dog 【】{
    【】
    【】
}
//基于Animal类,定义山羊类Goat,并重写两个抽象方法
class Goat 【】{
    【】
    【】
}
public class Main {
  public static void main(String[] args) {        
       Cat cat = new Cat();
       Dog dog = new Dog();        
      Goat goat = new Goat();
       speak(cat);
       speak(dog);
       speak(goat);
  }
  //定义静态方法speak()
 public static void speak(Animal animal) {
    if(animal instanceof Cat) {
        Cat cat = new Cat();
         cat.shout();
    }
    if(animal instanceof Dog) {
        Dog dog = new Dog();
         dog.shout();
    }
    if(animal instanceof Goat) {
        Goat goat = new Goat();
         goat.shout();
    }
 }

}

//定义抽象类Animal
abstract class Animal{
  public abstract Animal getAnimalClass();
  public abstract void shout();
}
//基于Animal类,定义猫类Cat,并重写两个抽象方法
class Cat extends Animal{
    public Animal getAnimalClass() {
        Animal cat = new Cat();
        return cat;
    }
    public void shout() {
        System.out.println("猫的叫声:喵喵");
    }
}
//基于Animal类,定义狗类Dog,并重写两个抽象方法
class Dog extends Animal{
public Animal getAnimalClass() {
    Animal dog = new Dog(); 
        return dog;
    }
    public void shout() {
        System.out.println("狗的叫声:汪汪");
    }
}
//基于Animal类,定义山羊类Goat,并重写两个抽象方法
class Goat extends Animal{
public Animal getAnimalClass() {
    Animal goat = new Goat();
    return goat;
    }
    public void shout() {
        System.out.println("山羊的叫声:咩咩");
    }
}

输入样例:

 

输出样例:

猫的叫声:喵喵
狗的叫声:汪汪
山羊的叫声:咩咩

三、踩坑心得

有很多种可能的输入错误及特殊情况,需要注意小心

四、改进建议

无建议

五、总结

面向对象的特点

1 继承

一种联结类的层次模型,并且允许和鼓励类的重用,提供一种明确表达共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),原始类称为新类的基类(父类)。派生类可以从它的父类哪里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。因此可以说,继承为了重用父类代码,同时为实现多态性作准备。

2 封装

封装是面向对象的特征之一,是对象和类概念的主要特性。封装就是把过程和数据包围起来,对数据的访问只能通过已定义的界面。隐藏复杂的特点,使交互变得更简单。
封装保证了模块具有较好的独立性,使得程序维护修改较为容易。对应用程序的修改仅限于类的内部,因而可以将应用程序修改带来的影响减少到最低限度。

3多态

多态是指允许不同类的对象对同一消息做出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活/抽象/行为共享/代码共享的优势,使程序拥有更强的动态扩展能力

 

ArrayList常用方法总结

List接口常用方法:
1、add(Object element): 向列表的尾部添加指定的元素。

2、size(): 返回列表中的元素个数。

3、get(int index): 返回列表中指定位置的元素,index从0开始。

4、add(int index, Object element): 在列表的指定位置插入指定元素。

5、set(int i, Object element): 将索引i位置元素替换为元素element并返回被替换的元素。

6、clear(): 从列表中移除所有元素。

7、isEmpty(): 判断列表是否包含元素,不包含元素则返回 true,否则返回false。

8、contains(Object o): 如果列表包含指定的元素,则返回 true。

9、remove(int index): 移除列表中指定位置的元素,并返回被删元素。

10、remove(Object o): 移除集合中第一次出现的指定元素,移除成功返回true,否则返回false。

11、iterator(): 返回按适当顺序在列表的元素上进行迭代的迭代器。

ArrayList一样可以使用List的所有方法,所以以ArrayList来演示:

方法使用:
1、add(Object element) 向列表的尾部添加指定的元素。
2、size() 返回列表中的元素个数。
3、get(int index) 返回列表中指定位置的元素,index从0开始。

例如:

import java.util.ArrayList;

public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>(); //<String>泛型表示集合中存的是字符串形式的元素。
list.add("徐冰"); //add()用于向List集合容器中添加元素。
list.add("萤火");
System.out.println(list);
System.out.println(list.size()); //size()用于获取集合中有多少个元素。
System.out.println(list.get(1)); //get()获取指定索引(从0开始)位置的元素。
}
}

输出:
[徐冰, 萤火]
2
萤火

4、add(int index, Object element) 在列表的指定位置(从0开始)插入指定元素。
例如:

import java.util.ArrayList;

public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("徐冰");
list.add("萤火");
System.out.println(list);
list.add(1, "阿若"); //在指定位置添加元素,原来位置的元素后置。
System.out.println(list);
}
}

 

输出:
[徐冰, 萤火]
[徐冰, 阿若, 萤火]

5、set(int i, Object element) 使用元素element替换索引i位置的元素,并返回被替换的元素。
例如:

import java.util.ArrayList;

public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("徐冰");
list.add("萤火");
System.out.println(list);
list.set(1, "阿若"); //替换指定位置的元素,从0开始,替换了“萤火”。
System.out.println(list);
}
}

 

输出:
[徐冰, 萤火]
[徐冰, 阿若]

6、clear() 从列表中移除所有元素。
7、isEmpty() 判断列表是否包含元素,不包含元素则返回 true,否则返回false。
例如:

import java.util.ArrayList;

public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("徐冰");
list.add("萤火");
System.out.println(list);
list.clear(); //清空List集合中的所有元素。
System.out.println(list.isEmpty()); //集合容器没有元素,则true。
System.out.println(list);
}
}

 

输出:
[徐冰, 萤火]
true
[]

8、contains(Object o) 如果列表包含指定的元素,则返回 true。
例如:

import java.util.ArrayList;

public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("徐冰");
list.add("萤火");
boolean flag = list.contains("徐冰"); //用来判断集合容器中是否含有参数元素。
System.out.println(flag);
}
}

 


这个方法需要思考一下,因为contains的参数类型是Object型,看一下源代码:

public boolean contains(Object o) {
return indexOf(o) >= 0;
}

public int indexOf(Object o) { //因为我们设置的实参是String类型的变量,所以此时o为上转型对象。
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
//因为o为上转型对象,所以equals表面上是Object类的,但实际上我们使用的是String类的equals方法。
return i;
}
return -1;
}

 


即list为上转型对象,使用String类的equals方法比较的是两个元素的内容是否相同。

9、remove(int index) 移除列表中指定位置的元素,并返回被删元素,删除位置后面的元素(如果有)向前移动。
例如:

import java.util.ArrayList;

public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("徐冰");
list.add("萤火");
list.add("阿若");
System.out.println(list.remove(1)); //删除指定索引(从0开始)位置的元素,并将元素返回,并后面元素前移。
System.out.println(list);
}
}

 


输出:
萤火
[徐冰, 阿若]

10、remove(Object o) 从List集合中移除第一次出现的指定元素,移除成功返回true,否则返回false。当且仅当List集合中含有满足(o==null ? get(i)==null : o.equals(get(i)))条件的最低索引i的元素时才会返回true。
例如:

import java.util.ArrayList;

public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("徐冰");
list.add("萤火");
list.add("阿若");
System.out.println(list.remove("萤火")); //删除List集合元素,返回boolean,并后面元素前移。
System.out.println(list);
}
}

 


输出:
true
[徐冰, 阿若]

11、iterator() 返回按适当顺序在列表的元素上进行迭代的迭代器。
例如运用iterator方法进行List遍历:

import java.util.ArrayList;
import java.util.Iterator;

public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("徐冰");
list.add("萤火");
Iterator<String> ite = list.iterator(); //将List集合中元素转到iterator变量中。
while(ite.hasNext()) //hasNext()判断当前“指针”下面是否还有元素的方法,java中没有指针,这只是举个例子。
{
System.out.println(ite.next()); //如果“指针”下面有元素,则移动“指针”并获取相应位置的元素。
}
}
}

 


输出:
徐冰
萤火

12、for循环遍历List集合:
例如:

import java.util.ArrayList;

public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("徐冰");
list.add("萤火");
for (int i = 0; i < list.size(); i++) { //用size方法获取长度。
System.out.println(list.get(i)); //用get方法获取值。
}
}
}

 


输出:
徐冰
萤火

13、加强for循环遍历List集合:
例如:

import java.util.ArrayList;

public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("徐冰");
list.add("萤火");
for (String name : list) { //使用foreach进行遍历。
System.out.println(name);
}
}
}

输出:
徐冰
萤火

抽象类和接口_接口interface
1.接口技术,这种技术主要用来描述类具有什么功能,而并不给出每个功能的具体实现.一个类可以实现一个或多个接口,并在需要接口的地方随时使用实现了相应接口的对象.
2.在Java程序设计语言中,接口不是类,而是一组对类的需求描述.接口中所有方法都自动地属于public.因此在接口中声明方法是,不必提供关键字public.
3.接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。面向对象的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如 C++、Java、C#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。
4.为什么需要接口?接口和抽象类的区别
 接口就是比“抽象类”还“抽象”的“抽象类”,可以更加规范的对子类进行约束。全 面地专业地实现了:规范和具体实现的分离。
 抽象类还提供某些具体实现,接口不提供任何实现,接口中所有方法都是抽象方法。接口是完全面向规范的,规定了一批类具有的公共方法规范。
 从接口的实现者角度看,接口定义了可以向外部提供的服务。
 从接口的调用者角度看,接口定义了实现者能提供那些服务。
5.接口格式

是 public 或默认。
 接口名:和类名采用相同命名机制。
 extends:接口可以多继承。
 常量:接口中的属性只能是常量,总是:public static final 修饰。不写也是。
 方法:接口中的方法只能是:public abstract。 省略的话,也是 public abstract。
6.要点

 子类通过 implements 来实现接口中的规范。
 接口不能创建实例,但是可用于声明引用变量类型。
 一个类实现了接口,必须实现接口中所有的方法,并且这些方法只能是 public 的。
 JDK1.8(不含 8)之前,接口中只能包含静态常量、抽象方法,不能有普通属性、构造方法、普通方法。
 JDK1.8(含 8)后,接口中包含普通的静态方法、默认方法。

抽象类和接口_静态方法和默认方法
1.JAVA8 之前,接口里的方法要求全部是抽象方法。
2.JAVA8(含 8)之后,以后允许在接口里定义默认方法和类方法(静态方法)。
默认方法
3.Java 8 及以上新版本,允许给接口添加一个非抽象的方法实现,只需要使用 default 关键字即可,这个特征又叫做默认方法(也称为扩展方法)。
 默认方法和抽象方法的区别是抽象方法必须要被实现,默认方法不是。作为替代方式,接口可以提供默认方法的实现,所有这个接口的实现类都会通过继承得到这个方法。
4.静态方法
 JAVA8 以后,我们也可以在接口中直接定义静态方法的实现。这个静态方法直接从属于接口(接口也是类,一种特殊的类),可以通过接口名调用
 如果子类中定义了相同名字的静态方法,那就是完全不同的方法了,直接从属于子类。 可以通过子类名直接调用。

抽象类和接口_多继承

接口完全支持多继承。和类的继承类似,子接口扩展某个父接口,将会获得父接口中所定义的一切

抽象类和接口_面向接口编程

  1. 面向接口编程是面向对象编程的一部分。
    2.为什么需要面向接口编程? 软件设计中最难处理的就是需求的复杂变化,需求的变化更多的体现在具体实现上。我们的编程如果围绕具体实现来展开就会陷入”复杂变化”的汪洋 大海中,软件也就不能最终实现。我们必须围绕某种稳定的东西开展,才能以静制动,实现 规范的高质量的项目。
    3.接口就是规范,就是项目中最稳定的核心! 面向接口编程可以让我们把握住真正核心的东西,使实现复杂多变的需求成为可能。
    4.通过面向接口编程,而不是面向实现类编程,可以大大降低程序模块间的耦合性,提高 整个系统的可扩展性和和可维护性。

 

 

都摘抄于CSDN

posted @ 2022-06-10 15:37  MQ202120  阅读(651)  评论(0)    收藏  举报