实验6-1

题目描述

定义一个 Card 类,代表与账户关联的银行卡。
要求:

  • 包含属性:卡号(cardNumber)、关联账户(linkedAccount)、余额(balance)、卡状态(active)
  • 实现方法generateCard()生成卡号,卡号的生成规则如下:
    • 固定前缀:6228
    • 中间段:利用inkedAccount的hashCode,取模 10^8 保证 8 位,格式化成 8 位十进制,不足前面补 0

输入格式

输入账号编号

输出格式

输出卡号

输入样例

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

123456789

输出样例

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

622827588661

这个题正好是我的知识点盲区,我对重写hashcode方法及其用法不是那么的会,所以当场就没写出来,的确,我在某些基础知识点方面很有欠缺的,面向对象只是常见的很熟练,有些真的就不熟甚至不会,所以我在系统性学他的用法,小总结如下:

//在示范equals和hashCode方法中,我需要写一个Person类,我们知道在Java中,对象默认继承Object类,
// Object类中的equals方法比较的是两个对象是否相等,Object类中的hashCode方法返回的是对象的哈希值,
// Object类中的hashCode方法返回的是对象的哈希值,二者一般都要重写。
public class Person extends Object{
    private String name;
    private int age;
    public Person() {
        super();
    }
    public Person(String name, int age) {
        super();
        try {
            setName(name);
            setAge(age);
        } catch (Exception e) {
            System.err.println("创建对象失败!" + e.getMessage());
            e.printStackTrace();
            throw new RuntimeException("对象创建失败!" + e);
        }
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        if(name==null||name.isEmpty()){
            throw new RuntimeException("姓名不能为空!");
        }else{
            this.name = name;
        }
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        if(age<0||age>120){
            throw new RuntimeException("年龄无效!");
        }else{
            this.age = age;
        }
    }
    @Override
    public String toString() {//重写toString方法,如果你不重写toString方法,那么打印对象时,打印的是对象的地址。
        return "Person [name=" + name + ", age=" + age + "]";
    }
    @Override
    public boolean equals(Object obj) {// 重写 equals 方法,目的是比较两个对象是否相等
        if (this == obj)//判断对象是否为同一个对象
            return true;
        if (obj == null)//判断对象是否为空
            return false;
        if (getClass() != obj.getClass())//判断对象是否为同一个类
            return false;
        Person other = (Person) obj;//强转对象,定义出一个Person对象
        if (age != other.age)//判断年龄是否相等
            return false;
        if (name == null) {//判断姓名是否为空
            //在上述情况下,名字要么为空,要么就和形参 other.name 相等
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
    @Override
    public int hashCode() { // 重写 hashCode 方法,目的是根据对象的属性计算出一个唯一的整数(哈希值)
        // 定义一个质数 31。
        // 为什么是 31?因为它是奇素数,能减少哈希冲突,且 JVM 能将其乘法运算优化为位移运算 (i << 5) - i,性能极高。
        final int prime = 31;
        // 初始化一个非零的起始值。
        // 如果初始为 0,第一个参与计算的字段会被“吞掉”(0 * 31 = 0),导致哈希分布不均匀。
        int result = 1;
        // 将基本数据类型字段(age)加入哈希计算。
        // 核心公式:result = 31 * 上一次的 result + 当前字段的值
        result = prime * result + age;
        // 将引用类型字段(name)加入哈希计算。
        // 这里做了一个极其重要的防御性编程:如果 name 为 null,则用 0 代替,防止空指针异常(NullPointerException)。
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        // 返回最终计算出的哈希值
        return result;
    }
}

不过实际上我们在计算哈希值的时候,可以直接调方法,如对象.hashcode();这是直接调用了他的object自带方法,所以这道题的代码就好写了,不过还有一个坑,先看代码:

import java.io.*;
import java.util.*;
public class Main {
    public static class Card {
        public String cardNumber;
        public String linkedAccount;
        public int balance = 0;//初始化我们的余额就是0
        public boolean active = true;
        public Card(String linkedAccount) {//带参构造
            this.linkedAccount = linkedAccount;
        }
        public void generateCard() {
            String prefix = "6228";
            int hash = linkedAccount.hashCode();
            //这个计算num的是为了防止负数的出现,就是利用了同余原理
            //在同余原理中,同余原理就是防止在数字量过大是时爆掉此数据类型,同时起到防负数的影响的作用
            //公式为(a + b) % m = (a % m + b % m) % m
            //不过他为什么可以去除负数的影响?
            //举个例子就如果说如果我们生成的哈希值是负的,那直接模出来的就会为负,那我们加上一个模数,但模出来的小数位还是不变的,但却可以去除负数的影响
            int num = (hash % 100000000 + 100000000) % 100000000;
            String middle = String.format("%08d", num);
            this.cardNumber = prefix + middle;
        }
    }
    public static void main(String[] args)throws  IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(System.out);
        String linkedAccountInput =br.readLine().trim();
        Card card = new Card(linkedAccountInput);
        card.generateCard();
        out.println(card.cardNumber);
        out.flush();
        br.close();
        out.close();
    }
}

6-2ATM加密接口

题目描述

定义接口 Encryptable,声明 encrypt(String data) -> String,利用base64进行数据加密。
定义ATM类,并实现取款功能drawal(),按面额优先给出最优解。面额包括:100、50、20、10。
对输出的面额详情进行加密,例如对“100元+3张”进行加密输出

输入格式

输入取款金额

输出格式

输出加密的取款详情

输入样例

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

100

​输出样例

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

MTAw5YWDKzHlvKA=

这个题,我在一开始是没看懂题的,只能说我的知识面它窄了,我们先要知道base64是什么:

不过它怎么编码的其实不重要,根据题目来然后了解基本用法就行

①首先在使用他之前要导包import java.util.Base64;

②第二它可以对二进制转为编码:

String str="Hello123";

byte[] bytes = str.getBytes();//用转换字节把他变为二进制

String encode = Base64.getEncoder().encodeToString(bytes);//直接用就行

那代码如下:

import java.util.*;
import java.io.*;
interface Encryptable{
    String encrypt(String data);
}
 class ATM implements Encryptable{
    @Override
    public String encrypt(String data) {
        return Base64.getEncoder().encodeToString(data.getBytes());
    }
    public void drawal(int n){
        StringBuilder sb = new StringBuilder();
        PrintWriter out = new PrintWriter(System.out);
        int[] money = {100,50,20,10};//就是简单的贪心
        for(int i=0;i<4;i++) {
            if(n>=money[i]) {//在大于此面额的时候,我们才进行此次换算
                int temp =n/money[i];
                String s=money[i]+"元+"+temp+"张";
                out.println(encrypt(s));
                n%=money[i];
            }
        }
    }
}
public class Main {
    public static void main(String[] args) {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int money = 0;
        try {
            money = Integer.parseInt(br.readLine().trim());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        ATM atm = new ATM();
        atm.drawal(money);
    }
}

最后要补充面向对象中的工具instanceof,首先我们要知道它的作用:判断一个对象 到底是什么类型(专门用于多态 / 父类引用指向子类对象的场景)代码如下:

我们先定义一个Animal类做父类:

public class Animal {
    public  void behavior() {
        System.out.println("我是父类的behavior方法");
    }
}

定义猫Cat类继承:

public class Cat extends Animal{
       @Override
       public void behavior(){//重写父类的behavior方法
           System.out.println("猫在睡觉");
       }
       public void meow(){
           System.out.println("喵喵喵~~~");
       }
}

定义狗Dog类继承:

public class Dog extends Animal{
    @Override
    public  void behavior(){
        System.out.println("狗在睡觉");
    }
    public void bark(){
        System.out.println("汪汪汪~~~");
    }
}

定义猪Pig类继承:

public class Pig extends  Animal{
    @Override
    public void behavior(){
        System.out.println("猪在睡觉");
    }
    public void oink(){
        System.out.println("哼哼哼~~~");
    }
}

定义鸭子类Duck继承:

public class Duck extends Animal{
    @Override
    public void behavior(){
        System.out.println("鸭在水中休息");
    }
    public void quack(){
        System.out.println("嘎嘎嘎~~~");
    }
}

定义鸟Bird类继承:

public class Bird extends  Animal{
    @Override
    public  void behavior(){
        System.out.println("鸟在树上休息");
    }
    public void chirp(){
        System.out.println("叽叽叽~~~");
    }
}

最后在主测试类里测试,代码如下:

public class Main{
    public static void main(String[] args){
        Animal []animals=new Animal[5];//定义一个动物类数组
        animals[0]=new Bird();
        animals[1]=new Cat();
        animals[2]=new Dog();
        animals[3]=new Bird();
        animals[4]=new Duck();
        for(Animal animal:animals){
            animal.behavior();
        }
        for (Animal animal : animals) {//判断他的类型然后强转
            if (animal instanceof Bird) {
                ((Bird) animal).chirp();
            } else if (animal instanceof Cat) {
                ((Cat) animal).meow();
            } else if (animal instanceof Dog) {
                ((Dog) animal).bark();
            } else if (animal instanceof Duck) {
                ((Duck) animal).quack();
            }
        }
    }
}

总结一下,对我来说在学习的过程中确实会有很多遗漏的知识点没能掌握,也有很多学过的知识点容遗忘,但是多写代码对知识点的记忆是会有很大益处的,现在是计科的学生,以后成为码农后,代码的敲击是要日复一日来提升自己的,虽然说有AI的帮助,但自己会了才是真的会,没办法,学识浅薄,仍需努力!

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐