综合案例

    此前我们已经练习了根据集合当中的字符串对象读写文件,而本综合案例主要练习根据集合当中的自定义对象来读写文件。

场景介绍

    很多网络游戏当中都有组队模式,例如魔兽世界、DotA、英雄联盟(LOL)、王者荣耀等,均为5人组队进行游戏。即使在现实生活中,打麻将、斗地主也都是多人进行的游戏。那么对于多人组队的游戏,典型的场景为:

    1.有5个人都在玩游戏;

    2.这5个人组成一个队伍;

    3.这支队伍进行游戏;

    4.队伍成员彼此欣赏,决定以后还要组队一起玩;

    5.一段时间后大家再次组队游戏。

分析整体思路

    

实现

  框架代码

//自定义一个类,代表英雄

public class Hero {

    //成员变量

    private String name;   //名字

    private int attack;    //英雄的攻击力

    private String type;   //英雄的类型

    public Hero() {

    }

    public Hero(String name, int attack, String type) {

        this.name = name;

        this.attack = attack;

        this.type = type;

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public int getAttack() {

        return attack;

    }

    public void setAttack(int attack) {

        this.attack = attack;

    }

    public String getType() {

        return type;

    }

    public void setType(String type) {

        this.type = type;

    }

}
//测试类

public class Test {

    public static void main(String[] args) {

        //1.首先创建一个集合,用来存储五个英雄

        ArrayList<Hero> list = new ArrayList<>();

        //2.读文件,把数据加到集合当中.

        System.out.println("加载文件的数据到集合当中.");

        //list.add(new Hero());    //假设已经从文件当中加载得到了数据,并且加入集合当中

        //3.判断一下集合当中有没有内容,是不是新的?

        boolean isNew = list.size() == 0; //如果集合的长度为0,说明这是新的队伍

        System.out.println("这是不是新队伍:" +isNew);

        //如果是新的队伍,没有人,就需要创建五个对像加入到集合当中

        if(isNew) {

            System.out.println("创建5个对象加入集合中.");

        }

        //如果不是新的队伍,已经有人了,就不需要创建了.

        System.out.println("我们队伍的阵容是:");

        //遍历集合,输出其中的每一个对象的具体信息

        System.out.println("循环5次进行遍历");

        //统计一下总和战斗力是多少.

        int totalAttack = 0;   //稍后在计算

        System.out.println("我们队伍的总战斗力是:" + totalAttack);

        //判断一下集合是不是新的

        if(isNew) {

            System.out.println("将集合的数据写到文件中.");

        }

        //如果集合不是新的,而是从文件中加载得到的数据,就什么都不用做

        System.out.println("退出游戏");

    }

}

英雄问世(创建对象)

  在测试类mian方法外添加方法

/*

     * 定义一个方法,用来向集合当中添加五位英雄.三要素: 返回值类型: 参数集合是引用类型,形式参数的操作会影响实际参数,所以不需要返回值,void 方法名称:

     * addFiveHeros 参数列表: ArrayList<Hero>

     */

    public static void addFiveHeros(ArrayList<Hero> list) {

        // 英雄信息来自于键盘输入(Scanner)

        Scanner sc = new Scanner(System.in); // 创建一个Scanner用来进行键盘输入

        for (int i = 1; i <= 5; i++) { //循环5次

            //键盘输入英雄的三个信息

            System.out.println("请输入第" + i + "英雄的名字:");

            String name = sc.next();   //获取字符串

            System.out.println("请输入第" + i + "英雄的攻击力:");

            int attack = sc.nextInt(); //获取int数字

            System.out.println("请输入第" + i + "英雄的类型:");

            String type = sc.next();

            Hero hero = new Hero(name,attack,type);   //创建一个英雄对象

            list.add(hero);    //把英雄对象添加到集合当中

        }

    }

main方法对应的地方调用方法进行添加

    

    // 如果是新的队伍,没有人,就需要创建五个对像加入到集合当中

        if (isNew) {

            //调用方法,向集合当中添加五个英雄

            addFiveHeros(list);

        }

阵容展示(遍历集合)

在测试类mian方法外添加遍历方法

 /*

     * 定义一个方法,用来遍历集合当中所有对象的信息,三要素:

     * 返回值类型:只是进行打印输出而已,所以使用void

     * 方法名称:showHeros

     * 参数列表:ArrayList<Hero>

     */

    public static void showHeros(ArrayList<Hero> list) {

        for (int i = 0; i < list.size(); i++) {

            Hero hero = list.get(i);   //当前英雄

            System.out.println("英雄名字: " + hero.getName() + ",攻击力:" + hero.getAttack() + ",类型:" + hero.getType());

        }

    }

mian方法中调用相应的方法进行遍历

  

    System.out.println("我们队伍的阵容是:");

        // 遍历集合,输出其中的每一个对象的具体信息

        showHeros(list);

战力计算(对象成员变量求和)

在测试类mian方法外添加计算方法

/*

     * 定义一个方法,用来根据集合求出战斗力总值.三要素:

     * 返回值类型:int,代表结果总和

     * 方法名称:getTotalAttack

     * 参数列表:ArrayList<Hero>

     */

    public static int getTotalAttack(ArrayList<Hero> list) {

        int total = 0; //代表总攻击力

        for (int i = 0; i < list.size(); i++) {

            Hero hero = list.get(i);

            //将每个英雄的战斗力全都累加到total当中

            total += hero.getAttack();

        }

        return total;

    }

mian方法中调用相应的方法进行计算

    // 统计一下总和战斗力是多少.
  
int totalAttack = getTotalAttack(list); //根据集合的内容求出总攻击力 System.out.println("我们队伍的总战斗力是:" + totalAttack);

桃园结义(写文件)

  在测试类main方法外添加写入文件数据方法

/*

     * 定义一个方法,用来将集合当中的对象数据全部都写到文件里.三要素:

     * 返回值类型:void

     * 方法名称:saveToFile

     * 参数列表:ArrayList<Hero>

     */

    public static void saveToFile(ArrayList<Hero> list) throws IOException {

        BufferedWriter bw = new BufferedWriter(new FileWriter("friends.txt"));

        //遍历集合,一个对象一个对象地挨个儿写

        for (int i = 0; i < list.size(); i++) {

            Hero hero = list.get(i);   //当前英雄

            //需要将一个Hero对象转换成为字符串,将三个成员变量拼接成为一个字符串

            //后羿,200,射手

            //宫本武藏,1400,刺客

            //机器人300,500,辅助

            String  str =  hero.getName()+","+hero.getAttack()+","+hero.getType();

            //将对应的字符串写道文件中

            bw.write(str);

            bw.newLine();  //不要忘记把每个属性换行

        }

        bw.close();    //最后别忘记关闭流

    }

mian方法中调用相应的方法进行写文件

    // 判断一下集合是不是新的

        if (isNew) {

            saveToFile(list);  //调用方法将集合的信息写到文件中.报错记得抛异常

        }

再度相约(读文件)

  扩展知识:

    如何才能将一个字符串"100"转换成为Int数字100?

  格式:

    Integer.parseInt(String str);

    参数是字符串,返回值是int数字,可以将字符串转换成为int数字.

    但是有前提:这个参数字符串必须只含有数字,格式必须是int数字!

在测试类main方法外添加读取文件数据方法

/*

     * 定义一个方法,用来读取文件,将数据添加到集合当中.三要素:

     * 返回值类型:参数集合是引用类型,形式参数的操作会影响实际参数,所以void

     * 方法名称:loadFileToList

     * 参数列表:ArrayList<Hero>

     */

    public static void loadFileToList(ArrayList<Hero> list) throws NumberFormatException, IOException {

        BufferedReader br = new BufferedReader(new FileReader("friends.txt"));

        String line;   //代表一行字符串

        while((line = br.readLine()) != null){

            //需要将字符串转换成为一个Hero对象

            //首先将一个完整的字符串切分成为若干小段儿

            String[] array = line.split(",");

            String name = array[0];        //姓名

            //将字符串转换成为对应的int基本类型数字

            int attack = Integer.parseInt(array[1]);   //攻击力

            String type = array[2];        //类型

            //根据三条信息创建一个英雄对象

            Hero hero = new Hero(name,attack,type);  

            list.add(hero);    //将对象添加到集合当中

        }

        br.close();    //不要忘记关闭流

    }

mian方法中调用相应的方法进行读文件

    // 2.读文件,把数据加到集合当中.

        loadFileToList(list);

接口

  现实生活的接口举例

    

面向对象的接口思想

    

使用接口的好处

    

格式与组成部分

  

//接口的基本定义格式:
public interface 接口名称 {
//...
}

  接口当中可以包含的组成部分有:

  1. 抽象方法[今天学习的重点所在]
  2. 常量
  3. 默认方法(java 8)
  4. 静态方法(java 8)
  5. 私有方法(java 9)

抽象方法定义

    

/*

 * 如何定义一个抽象方法:  

 *      public abstract 返回值类型 方法名称(参数类型 参数名称);

 * 注意:

 *      1.接口中的抽象方法,修饰如果写必须是:public abstract

 *      2.接口中的抽象方法,修饰符可以省略不写,默认是:public abstract

 *      3.抽象方法只有方法头,不能有方法体大括号.

 */

public interface Animal {

    //定义了一个抽象方法,吃东西

    public abstract void eat();

    //定义了另一个抽象方法:睡觉

    //省略了public abstract也照样是抽象方法

    /*public abstract*/ void sleep();

}

  

实现类的定义

/*
* 如果想要使用定义好的接口,必须有一个接口的"实现类".
* 定义实现类格式为:
*
* public class 实现类名称 implements 接口名称 {
* //一定要覆盖重写所有的抽象方法
* }
* 什么是覆盖重写(Override)抽象方法?
* 1.将接口当中的抽象方法抄写过来
* 2.去掉abstract关键字
* 3.写上大括号方法体
*
* Cat就是Animal接口的实现类,Cat类实现了Animal接口.
*/
public class Cat implements Animal {
public void eat() {
System.out.println("猫吃鱼");
}
public void sleep() {
System.out.println("猫睡觉");
}
}

与实现类的基本使用

  

如何使用接口与实现类?
*
* 创建:
* 接口名称 引用名 = new 实现类名称();
*
* 调用:
* 引用名.抽象方法名(参数);
*
* 注意:
* 1.左边是接口类型,那么只能调用接口当中定义好的内容,不能调用右侧实现类当中特有的内容.(接口隔离)
* 2.当调用接口当中的抽象方法时,真正进行运行的是右侧new的时候类的具体方法内容.
* 总结:调用的时候看左边,运行的时候看右边.
*/ //实现类添加特有的方法:
public class Cat implements Animal {
//省略吃睡两个方法; //这是一个Cat自己特有的方法,接口当中并没有定义
public void catchMouse() {
System.out.println("猫抓老鼠");
}
} //接口调用特有方法 错误!
public class Demo01Interface {
public static void main(String[] args) {
//创建:
Animal cat = new Cat(); //省略调用吃睡两个方法 //cat.catchMouse(); //错误!无法调用右侧实现类专有的方法,只能调用接口的方法.
}
}

面向接口编程

 

//添加一个狗类
public class Dog implements Animal{
public void eat() {
System.out.println("狗吃骨头");
}
public void sleep() {
System.out.println("狗睡觉");
} //特有方法
public void watchHouse() {
System.out.println("狗看家");
}
} /*
* 使用接口作为左侧类型的好处所在:
* 屏蔽掉了右侧的个性特有的内容,达到隔离,统一的目的.
*
* 面向接口编程:
* 如果使用的功能,接口已经可以满足,那么就不在乎具体的类是谁,只在乎接口即可.
*/
public class Demo02Interface {
public static void main(String[] args) {
Cat cat = new Cat(); // 创建了一只猫
method(cat); // 将猫对象传递给方法,间接使用其中的eat和sleep方法. Dog dog = new Dog(); // 创建了一只狗
method(dog); } // 使用接口作为参数类型,这样就不区分到底是猫还是狗.
public static void method(Animal animal) {
animal.eat();
animal.sleep();
// animal.watchHouse(); //错误!无法调用狗的专有的方法
// animal.catchMouse(); //错误!无法调用猫的专有的方法
}
}

不必要的接口实现类

//定义一个计算器的接口
public interface Calculator {
public abstract int sum(int a,int b);
} //计算器接口的实现类
public class CalculatorImpl implements Calculator{
public int sum(int a,int b) {
int result = a + b;
return result;
}
} public class Demo01Calc {
public static void main(String[] args) {
//首先使用接口的格式来创建了一个计算器对象
Calculator calculator = new CalculatorImpl(); //将计算器对象交给method方法去使用
method(calculator);
} //参数是接口类型,计算器接口
public static void method(Calculator calculator) {
int result = calculator.sum(10, 20);
System.out.println("结果是:"+result);
}
}

Lambda表达式

  体验Lambda表达式(新世界大门)

  

//定义一个计算器的接口

public interface Calculator {

    public abstract int sum(int a,int b);

}

//Lambda 函数式

public class Demo01Calc {

    public static void main(String[] args) {

        //将计算器对象交给函数式 method方法去使用

        method((a,b) -> a + b);

    }

    //参数是接口类型,计算器接口

    public static void method(Calculator calculator) {

        int result = calculator.sum(100, 200);

        System.out.println("结果是:"+result);

    }

}

理解Lambda的语义

//Lambda 函数式

public class Demo01CalcLambda {

    public static void main(String[] args) {

        method((a,b) -> a + b);

        //Lambda表达式:(a,b) -> a + b

        //method方法需要一个Calculator接口类型的参数

        //Lambda表达式就是充当了Calculator接口类型的参数

        //初步理解:

        //1.Lambda表达式前面的小括号,其实就是接口抽象方法的小括号.

        //2.箭头代表拿着小括号的数据做什么事情,是一个指向的动作.

        //3.箭头后面就代表拿到了参数之后做什么事情.

        //Lambda表达式的语义本身就代表了怎么做这件事情,没有对象的概念在里面.(更加简单直观.)

    }

    //参数是接口类型,计算器接口

    public static void method(Calculator calculator) {

        int result = calculator.sum(100, 200);

        System.out.println("结果是:"+result);

    }

}

函数式接口

/*

 * Java当中使用Lambda表达式的前提是:必须有"函数式接口".

 *

 * 概念:有且仅有一个抽象方法的接口,叫做函数式接口.

 * 可以同时有其它:默认方法、静态方法.....但不能再有抽象方法了

 *

 * 如何才能万无一失地检测一下当前接口是不是函数式接口呢?

 * 用一个固定的格式写在public interface之前一行即可:

 * @FunctionalInterface

 * public interface 函数式接口名{

 *      //...

 *}

 */

@FunctionalInterface

public interface Calculator {

    public abstract int sum(int a,int b);

}

标准格式

/*

 * Lambda表达式要想使用,一定要有函数式接口的推断环境。

 * 1.要么通过方法的参数类型来确定是哪个函数式接口

 * 2.要么通过赋值操作来确定是哪个函数式接口

 * Lambda的格式就是为了将抽象方法,翻译成为以下三点:

 * 1.一些参数(方法参数)

 * 2.一个箭头

 * 3.一些代码(方法体,大括号)

 * 例如抽象方法:

 * public abstract int sum(int a,int b);

 * 翻译成为Lambda的标准格式:

 * (int a,int b) -> { return a + b;}

 */

public class Demo03Lambda {

    public static void main(String[] args) {

        method( (int a,int b) -> { return a + b;} );

    }

    public static void method(Calculator calculator) {

        int result = calculator.sum(100, 200);

        System.out.println("结果是:"+result);

    }

}

上下文推断

public class Demo03Lambda {

    public static void main(String[] args) {

        //调用方法的时候,参数类型是函数式接口,所以Lambda可以推断出来是哪个接口

        method( (int a,int b) -> { return a + b;} );

        System.out.println("============================");

        //也可以根据赋值语句左侧的类型来进行Lambda上下文推断

        Calculator param = (int a,int b) -> { return a + b ; };

        method(param);

//      (int a,int b) -> { return a + b ; };  //错误写法! 没有上下文环境,Lambda就无法推断是哪个函数式接口

    }

    public static void method(Calculator calculator) {

        int result = calculator.sum(100, 200);

        System.out.println("结果是:"+result);

    }

}

简便格式

//注意!不管写不写@FunctionalInterface,只要是有且仅有一个抽象方法的接口,就是函数式接口!

@FunctionalInterface

public interface MyInter {

    //作用:将参数++,然后返回结果

    public abstract int singlePlus(int num);

}

/*

 * 在Lambda表达式当中,凡是可以推导的,都是可以省略的.

 * 1.Lambda表达式当中的参数类型可以省略不写.

 * 2.如果参数有且只有一个,那么小括号可以省略.

 * 3.如果语句只有一个,那么大括号和return也可以省略.

 */

public class DemoLambdaSimple {

    public static void main(String[] args) {

       //标准格式:

       method( (int x) -> { return ++x; } );

       //省略参数类型:

       method( (x) -> { return ++x; } );

       //省略参数小括号:

       method( x -> { return ++x; } );

       //省略大括号和return关键字:

       method( x -> ++x );

    }

    public static void method(MyInter inter) {

       int result = inter.singlePlus(10);

       System.out.println("结果:" + result);

    }

}

知识总结

  1.使用接口的好处:通用性、隔离性。

  2.定义接口的格式:

    

    public interface接口名{

     //...

    }

  3.接口的组成部分:

    a)抽象方法【核心内容】

    b)常量

    c)默认方法(Java8)

    d)静态方法(Java8)

    e)私有方法(Java9)

  4.定义一个抽象方法,格式:

    public abstract 返回值类型 方法名(参数类型参数名);

    a)修饰符 public abstract也可以省略不写

    b)抽象方法不可以写方法体大括号

  5.接口要想使用,一定要有一个实现类。如何实现?

  

public class类名称implements接口名{
//覆盖重写所有的抽象方法 }

  6.如何覆盖重写(Override)抽象方法呢?一般步骤:

    a)将抽象方法抄写过来

    b)去掉abstract关键字

    c)写上方法体

  7.使用接口和实现类的一般格式:

    a)创建:接口名称 引用名 = new实现类名称();

    b)调用:引用名.抽象方法名(参数);

    c)注意:

      i. 只能调用左侧接口当中定义好的方法,无法调用右侧类当中特有的方法。

      ii. 运行程序的时候,方法的执行者其实是右边的类对象。

      iii. "调用的时候看左边,但是运行的时候看右边”。

  8.从Java8开始,没有接口的实现类,也可以直接使用接口:Lambda表达式。Lambda表达式就替代了实现类。

  9.Lambda使用前提:一定要有函数式接口才能用,没有函数式接口就不能用Lambda表达式。

  10.函数式接口:有且仅有一个抽象方法的接口。无所谓有没有@FunctionalInterface,这是一个可选的检测手段而已。

  11.使用Lambda必须有推断环境:

    a)要么根据参数类型传参来推断函数式接口。

    b)要么就根据赋值语句左侧类型来推断函数式接口。

  12.Lambda表达式的标准格式:(int a,int b) -> { return a+b; }

    a) 一些参数(方法的参数)

    b)一个箭头

    c)一些代码(方法体)

  13.Lambda表达式的简便格式:

    (int num) -> { return ++num; }

    (num) -> { return ++num; }

    num -> { return ++num; }

    num -> ++num;

    a)参数的类型可以省略。

    b) 如果有且仅有一个参数,那么小括号可以省略

    c)如果有且仅有一个语句,那么大括号和return也可以省略

Java基础(九)的更多相关文章

  1. Java基础九--抽象类

    Java基础九--抽象类 一.抽象类介绍 /*抽象类:抽象:笼统,模糊,看不懂!不具体. 特点:1,方法只有声明没有实现时,该方法就是抽象方法,需要被abstract修饰. 抽象方法必须定义在抽象类中 ...

  2. java基础九[网络与线程](阅读Head First Java记录)

    网络socket连接 Java API的网络功能包(java.net)已经将底层的TCP连接等都封装好了,我们只需要通过Socket对象来建立客户端和服务器的连接,然后客户端能向服务器发送请求,并接收 ...

  3. 黑马程序员 Java基础<九>---> 多线程

    ASP.Net+Android+IOS开发..Net培训.期待与您交流! 多线程 一.概述: 1.线程是什么 说到线程,我们就得先说说进程.所谓进程,就是一个正在执行(进行)中的程序,每一个进程执行都 ...

  4. java基础( 九)-----深入分析Java的序列化与反序列化

    序列化是一种对象持久化的手段.普遍应用在网络传输.RMI等场景中.本文通过分析ArrayList的序列化来介绍Java序列化的相关内容.主要涉及到以下几个问题: 怎么实现Java的序列化 为什么实现了 ...

  5. Java基础(九)--反射

    什么是反射? 在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性 这种动态获取的信息以及动态调用对象的方法的功能称为反射机制. 反射的前 ...

  6. java基础(九) 可变参数列表介绍

    一.可变参数简介 在不确定参数的个数时,可以使用可变的参数列表. 1. 语法: 参数类型...(三个点) 例如: void printArray(Object...) 注意: 每个方法最多只有一个可变 ...

  7. java基础(九)--方法重载

    如System.out.println()方法即是方法重载的. 以下举例说明自定义sum()方法的重载 package cnblogs; public class TestBase09MathRelo ...

  8. java基础知识文章汇总

    将之前的所有关于Java基础知识的随笔,整理成质量较高的十几篇随笔,几乎是好几篇比较零散的随笔合成现在的一篇,自认为还不错. java基础(一) 深入解析基本类型 java基础(二) 自增自减与贪心规 ...

  9. Java语言基础(九)

    Java语言基础(九) 一.自增运算(++) 自减运算(--) i++ 就是将i+1再赋给 i i-- 是将i-1再赋给 i 对变量i,j来说,i++ 或++i 这里没什么区别,都是将i的值加1后,再 ...

随机推荐

  1. BZOJ 1778: [Usaco2010 Hol]Dotp 驱逐猪猡 概率与期望+高斯消元

    这个还挺友好的,自己相对轻松能想出来~令 $f[i]$ 表示起点到点 $i$ 的期望次数,则 $ans[i]=f[i]\times \frac{p}{q}$ #include <cmath> ...

  2. Java根据余弦定理计算文本相似度

    项目中需要算2个字符串的相似度,是根据余弦相似性算的,下面具体介绍一下: 余弦相似度计算 余弦相似度用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小.余弦值越接近1,就表明夹角越接近0度, ...

  3. zabbix服务端接收的数据类型,便于编写脚本向服务端提交数据

    1.数据类型1:zabbix_agent执行脚本提交字典 UserParameter=tcp_port_listen,/usr/local/zabbix/share/script/get_game_p ...

  4. 使用fiddler实现手机抓包

    手机上无法直接查看网络请求数据,需要使用抓包工具.Fiddler是一个免费的web调试代理,可以用它实现记录.查看和调试手机终端和远程服务器之间的http/https通信. fiddler没有手机客户 ...

  5. node链接mongoDB及封装

    // 这个模块中封装所有对数据库的常用操作 const MongoClient = require('mongodb').MongoClient; const assert = require('as ...

  6. $\LaTeX$数学公式大全3

    $3\ Delimiters$$|$ |$\vert$ \vert$\|$ \|$\Vert$ \Vert$\{$ \{$\}$ \}$\langle$ \langle$\rangle$ \rangl ...

  7. finally的一个妙用

    ●传统用法try-catch-finally大家都会用:try包裹可能抛出异常的代码:catch捕获异常并对其处理:finally做一些资源关闭等回收工作.简单明了一句话就能说清. 稍微进阶一些的,大 ...

  8. 使用IDEA配置SpringBoot热部署无效解决

    首先检查自己pom.xml文件里是否有加入依赖 <dependency> <groupId>org.springframework.boot</groupId> & ...

  9. 2018-2019-2 20165215《网络对抗技术》Exp8 Web基础

    目录 实验内容 基础问题回答 实验步骤 (一)Web前端HTML (二) Web前端javascipt (三)Web后端:MySQL基础:正常安装.启动MySQL,建库.创建用户.修改密码.建表 (四 ...

  10. PHP压缩图片并模糊处理(抄的哟)

    class image_blur{ /** * 图片高斯模糊(适用于png/jpg/gif格式) * @param $srcImg 原图片 * @param $savepath 保存路径 * @par ...