【Java】基础12_内部类,Comparator与Comparable


1.内部类

package com.itheima05.innerclass;
/*
*   1. 定义在一个类A内部的另外一个类B, 那么A称之为外部类, B称之为内部类
*        内部类: 访问受限(要通过外部来访问内部)
*   2. 成员内部类: 定义一个类成员位置的类 (少见)
*        1. 语法:外部类名.内部类名(声明) 变量名 = 外部类对象.new 内部类();
*        2. 编译:多了一个:OuterClass$InnerClass.class
*   3. 局部内部类: 定义在一个方法里的类。只能当前方法内使用,其他方法不能使用
*/
public class InnerDemo {
    public static void main(String[] args) {
          class MethodClass{ //定义在main方法里称为局部内部类
              int methodField;
              void method(){
              }
          }
        MethodClass mc = new MethodClass();
        mc.methodField = 1;
        mc.method();
    }

    public static void method01(){
        OuterClass oc = new OuterClass();
        oc.outerField = 1;
        oc.outerMethod();

        OuterClass.InnerClass ic = oc.new InnerClass();
        ic.innerFiled = 2;
        ic.innerMethod();	
		// MethodClass mc = new MethodClass();//错误,不能访问
    }
}
//外部类
class OuterClass{
    int outerField; //成员
    void outerMethod(){ 
    }
    //成员内部类
    class InnerClass{
        int innerFiled;
        void innerMethod(){
        }
    }
}

在这里插入图片描述

1.1 匿名内部类

在这里插入图片描述

package com.itheima05.innerclass;
/*
*     1. 匿名内部类 属于 方法/局部内部类 的一种
*     2. 匿名内部类 没有 类名
*     3. 目的 : 简化代码编写
*         new 父类/父接口() {//class body 即类体
*              如果有抽象方法,必须重写
*          }
*        创建出来的是父类/父接口的子类对象
*        原理:  定义类+创建对象  合二为一
*/
public class InnerDemo02 {
    public static void main(String[] args) {
        Dog twoHa = new Dog();
        voice(twoHa); //汪汪叫

//		
        //InnerDemo02$Wolf.class //第一个内部类有名字Wolf   
		class Wolf implements Animal{
            @Override
            public void shout() {
                System.out.println("嗷嗷叫");
            }
        }
        Wolf greyTai = new Wolf();
        voice(greyTai); //嗷嗷叫

//
        /*
        * 类名如dog,wolf其实在某些场景下一定都不重要,重要的类体(重写shout方法)
        * 语法: 多了个类体,但是把类名隐藏掉了叫匿名
        * 省略: 1. 以前:  定义类  然后 创建对象
        *       2. 现在: 定义类+创建对象  合二为一
        */
		// Animal a = new Animal(); //接口不能实例化,如下加方法体        
        // 父接口 变量 = 父接口子类对象 (向上转型)
        Animal a = new Animal(){ //多了一个大括号,InnerDemo02$1.class 第二个内部类也是第一个匿名内部类用1
            @Override
            public void shout() {
                System.out.println("嘎嘎叫"); //代码同下
            }
        };
        voice(a); //嘎嘎叫

///
       // InnerDemo02$2.class  //第三个内部类也是第二个匿名内部类用2
       Animal b = new Animal(){
           @Override
           public void shout() {
               System.out.println("呱呱叫");
           }
       };
       voice(b); // 呱呱叫

/
        //匿名内部类的匿名对象,最简洁  //InnerDemo02$3.class
       voice(new Animal() {
           @Override
           public void shout() {
               System.out.println("喵喵叫"); // 喵喵叫
           }
       });
    }
	
/
    //Animal接口, 接口不能实例化
    private static void voice(Animal a) {
        a.shout();
    }
}
interface Animal{ //一般不用abstract Animal
    void shout(); //叫
}
class Dog implements Animal{ //多态
    @Override
    public void shout() {
        System.out.println("汪汪叫");
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如下这个类对象就用一次,没必要取个名字,如果取名字还要单独的.java文件
在这里插入图片描述

1.2 练习

在这里插入图片描述

package com.atguigu.test10;
/*
(1)声明一个抽象类Father,包含抽象方法:public abstract void method();
(2)用匿名内部类继承Father,并重写抽象方法,打印“hello 孩子"。并调用子类对象的method方法
*/
public class TestExer3 {
	public static void main(String[] args) {
		/*new Father(){
			public void method(){
				System.out.println("hello 孩子");
			}
		}.method();*/
		
		Father f = new Father(){
			public void method(){
				System.out.println("hello 孩子");
			}
		};
		f.method(); //hello 孩子
	}
}
abstract class Father{
	public abstract void method();
}

在这里插入图片描述

package com.atguigu.test10;

import java.util.Arrays;
import java.util.Comparator;
/*
(1)声明一个员工类Employee,有属性:编号、姓名、薪资
(2)在测试类中创建Employee数组
(3)分别调用Arrays.sort(数组,Comparator),用匿名内部类实现按照 编号 升序排列
(4)同上.......................................................薪资 ........
 */
public class TestExer4 {
	@SuppressWarnings("all")
	public static void main(String[] args) {
		//(2)在测试类中创建Employee数组
		Employee[] all = new Employee[3];
		all[0] = new Employee(2, "张三", 10000);
		all[1] = new Employee(1, "李四", 30000);
		all[2] = new Employee(3, "王五", 20000);
		
		//(3)分别调用Arrays.sort(数组,Comparator),用匿名内部类实现按照编号升序排列,接口一定要重写方法
		Arrays.sort(all, new Comparator(){
			@Override
			public int compare(Object o1, Object o2) {
				Employee e1 = (Employee) o1;
				Employee e2 = (Employee) o2;
				return e1.getId() - e2.getId();
			}			
		});
		for (int i = 0; i < all.length; i++) {
			System.out.println(all[i]);
		}
		
//		(4)分别调用Arrays.sort(数组,Comparator),用匿名内部类实现按照薪资升序排列
		Arrays.sort(all , new Comparator() {
			@Override
			public int compare(Object o1, Object o2) {
				Employee e1 = (Employee) o1;
				Employee e2 = (Employee) o2;				
				if(e1.getSalary() > e2.getSalary()){
					return 1;
				}else if(e1.getSalary() < e2.getSalary()){
					return -1;
				}
				return 0;
			}
		});
		for (int i = 0; i < all.length; i++) {
			System.out.println(all[i]);
		}
	}
}
//(1)声明一个员工类Employee,有属性:编号、姓名、薪资
class Employee{
	private int id;
	private String name;
	private double salary;
	public Employee(int id, String name, double salary) {
		super();
		this.id = id;
		this.name = name;
		this.salary = salary;
	}
	public Employee() {
		super();
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + "]";
	}	
}

在这里插入图片描述

2.练习题

2.1 模拟玩家选择角色

package com.atguigu.homework.test03;

import java.util.Scanner;
/*
* 定义接口FightAble:
  * 抽象方法:specialFight。
  * 默认方法:commonFight,方法中打印"普通打击"。
* 定义战士类:
  * 实现FightAble接口,重写方法中打印"武器攻击"。
* 定义法师类Mage:
  * 实现FightAble接口,重写方法中打印"法术攻击"。
* 定义玩家类Player:
  * 静态方法:FightAble select(String str),根据指令选择角色。
    * 法力角色,选择法师。
    * 武力角色,选择战士。
 */
public class Test03 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		System.out.print("选择:");
		String role = input.next();		
		FightAble f = Player.select(role);
		f.specialFight();
		f.commonFight();
		
		System.out.println("================");
		System.out.print("选择:");
		String role2 = input.next();		
		FightAble f2 = Player.select(role2);
		f2.specialFight();
		f2.commonFight();
	}
}
interface FightAble{
	void specialFight();
	public default void commonFight(){
		System.out.println("普通打击");
	}
}
class Soldier implements FightAble{
	@Override
	public void specialFight() {
		System.out.println("武器攻击");
	}	
}
class Mage implements FightAble{
	@Override
	public void specialFight() {
		System.out.println("法术攻击");
	}	
}
class Player{
	public static FightAble select(String str){
		if("法力角色".equals(str)){
			return new Mage(); //com.itheima.demo01.Mage@610455d6
		}else if("武力角色".equals(str)){
			return new Soldier();
		}
		return null; //函数不是void要有返回值
	}
}

在这里插入图片描述

2.2 模拟人工挑苹果

在这里插入图片描述

package com.atguigu.homework.test04;

public class Test04 {
	public static void main(String[] args) {
		Worker w = new Worker();	
		Apple a1 = new Apple(5.0, "青色");
		Apple a2 = new Apple(3.0, "红色");
		CompareBig cb = new CompareBig();
		w.pickApple(cb, a1, a2);		
		CompareColor cc = new CompareColor();
		w.pickApple(cc, a1, a2);
	}
}
package com.atguigu.homework.test04;

public class Apple {
	private double size;
	private String color;
	public Apple(double size, String color) {
		super();
		this.size = size;
		this.color = color;
	}
	public Apple() {
		super();
	}
	public double getSize() {
		return size;
	}
	public void setSize(double size) {
		this.size = size;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	@Override
	public String toString() {
		return size + "-" + color;
	}	
}
package com.atguigu.homework.test04;

public interface CompareAble {
	//定义默认方法compare,挑选较大苹果。
	public default void compare(Apple a1, Apple a2){
		if(a1.getSize() > a2.getSize()){
			System.out.println(a1);
		}else{
			System.out.println(a2);
		}
	}
}
package com.atguigu.homework.test04;

public class CompareBig implements CompareAble{
}
package com.atguigu.homework.test04;

public class CompareColor implements CompareAble{
	public void compare(Apple a1, Apple a2){
		if("红色".equals(a1.getColor())){
			System.out.println(a1);
		}
		if("红色".equals(a2.getColor())){
			System.out.println(a2);
		}
	}
}
package com.atguigu.homework.test04;

//挑选苹果public void pickApple(CompareAble c,Apple a1,Apple a2)。
public class Worker {
	public void pickApple(CompareAble c,Apple a1,Apple a2){
		c.compare(a1, a2);
	}
}

在这里插入图片描述
将上面改为匿名内部类实现接口来代替CompareBig和CompareColor
在这里插入图片描述

2.3 数组工具类

package com.atguigu.test04;
/*
 编写一个MyArrays的数组工具类,这个工具类,想要为任意的对象数组,进行升序排序。Comparator实现类与Arrays.sort方法
*/
public class TestComparator2 {
	public static void main(String[] args) {
		Student[] all = new Student[5];
		all[0] = new Student("杨洪强", 24, 89);
		all[1] = new Student("苏海波", 23, 100);
		all[2] = new Student("张三",23,88);
		all[3] = new Student("李四",24,44);
		all[4] = new Student("王五",25,45);
		
		AgeComparator c = new AgeComparator();
		MyArrays.sort(all, c); //静态方法:类名.
		
		for (int i = 0; i < all.length; i++) {
			System.out.println(all[i]);//打印对象,自动调用对象toString
		}
	}
}
package com.atguigu.test04;

import java.util.Comparator;//JDK的核心类中写好的,不用我们写
/*
 * 需求:编写一个MyArrays的数组工具类,这个工具类,想要为任意的对象数组,进行升序排序
 */
public class MyArrays {
	public static void sort(Object[] arr, Comparator c){
		for (int i = 1; i < arr.length; i++) {
			System.out.println("第" + i +"轮");
			for (int j = 0; j < arr.length-i; j++) {
				System.out.println("比较:arr["+j+"]和arr["+(j+1)+"]");
				System.out.println(arr[j]);
				System.out.println(arr[j+1]);
				System.out.println();
			//前面的元素对象  >  后面的元素对象,交换
			//if(arr[j] > arr[j+1]){ //这两个对象没办法比较
			//标准  Comparator 接口,里面有一个int compare(Object o1, Object o2)
			//规定:o1大于o2对象,一定返回正整数,o1小于o2对象,一定返回负整数,o1等于o2对象,一定返回0,
				if(c.compare(arr[j], arr[j+1]) > 0){//执行时,compare执行的是实现类的compare方法
					Object temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
				}
			}
		}
	}
}
package com.atguigu.test04;

import java.util.Comparator; //第一步导包

public class AgeComparator implements Comparator{ //第二步重写抽象方法
	@Override
	public int compare(Object o1, Object o2) {
		Student s1 = (Student) o1;
		Student s2 = (Student) o2;
		return s1.getAge() - s2.getAge();
		/*
		 * s1.getAge() 大于 s2.getAge() 正整数
		 */
	}
}
package com.atguigu.test04;

public class Student{
	private String name;
	private int age;
	private int score;
	public Student(String name, int age, int score) {
		super();
		this.name = name;
		this.age = age;
		this.score = score;
	}
	public Student() {
		super();
	}
	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 int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
	}	
}

2.4 Comparator和Comparable

// TestComparable.java
package com.atguigu.test05;
/*
 * java.util.Comparator:定制比较,定制顺序,是对自然比较的补充
 * 		int compare(Object o1, Object o2)://接口的抽象方法
 * 				o1与o2比较,o1>o2,返回正整数
 * 				o1与o2比较,o1<o2,返回负整数
 * 				o1与o2比较,o1=o2,返回0
 
 * java.lang.Comparable:自然比较,自然顺序,核心默认不用导包
 * 		int compareTo(Object obj)  //抽象方法要重写
 * 				this与obj对象比较,this > obj,返回正整数
 * 				this与obj对象比较,this < obj,返回负整数
 * 				this与obj对象比较,this = obj,返回0
 * 
 * 上午讲的定制比较器,用定制比较器的对象即如下c,比较两个学生对象:
 * 		AgeComparator c = new AgeComparator();
 * 		if(c.compare(s1, s2) > 0){...}
 * 
 * 希望学生对象本身就具备比较大小的能力。
 */
public class TestComparable {
	public static void main(String[] args) {
		Student s1 = new Student("杨洪强", 24, 89);
		Student s2 = new Student("苏海波", 23, 100);
		
		//按成绩比较,不用第三个对象了
		if(s1.compareTo(s2)>0){
			System.out.println("s1 > s2成绩");
		}else if(s1.compareTo(s2)<0){
			System.out.println("s1 < s2成绩");
		}else{
			System.out.println("s1 = s2成绩");
		}		
		//按年龄比较,只能再用定制比较,补充完成这个功能
	}
}
class Student implements Comparable{ //ctrl+1:add ynimplemented methods 重写compareTo方法
	private String name;
	private int age;
	private int score;
	public Student(String name, int age, int score) {
		super();
		this.name = name;
		this.age = age;
		this.score = score;
	}
	public Student() {
		super();
	}
	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 int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
	}
	@Override
	public int compareTo(Object obj) {
		//this与obj比较,this和obj都是学生对象
		Student other = (Student) obj;
		//例如:对于学生对象来说,最常用的是按成绩排名,那么我就可以把自然顺序定位成绩升序
/*		if(this.score > other.score){
			return 1;
		}else if(this.score < other.score){
			return -1;
		}
		return 0;*/		
		return this.score - other.score;
	}
}
package com.atguigu.test05;

import java.util.Arrays;
/*
 * Arrays的sort方法有两种:
 * (1)void sort(Object[] arr):
 * 		根据元素的自然顺序对指定对象数组按升序进行排序。数组中的所有元素都必须实现 Comparable 接口。
 * (2)void sort(Object[] arr, Comparator c):
 * 		根据“指定比较器”产生的顺序对指定对象数组进行排序。数组中的所有元素都必须是通过“指定比较器”可相互比较的
 */
public class TestArrays {
	public static void main(String[] args) {
		Student[] all = new Student[5];
		all[0] = new Student("杨洪强", 24, 89);
		all[1] = new Student("苏海波", 23, 100);
		all[2] = new Student("张三",23,88);
		all[3] = new Student("李四",24,44);
		all[4] = new Student("王五",25,45);
		
		//如果我们的学生类Student,实现了java.lang.Comparable接口,
		//能不能按照自然排序的规则进行排序呢
		//Arrays中有这样的方法
		//public static void sort(Object[] a)
		
		Arrays.sort(all);
		//这里面排序过程中,调用了元素本身的compareTo()方法
		//因为元素本身是Student类型,它实现了java.lang.Comparable接口
		//本身就具备比较大小的能力,即拥有compareTo()方法
		
		for (int i = 0; i < all.length; i++) {
			System.out.println(all[i]);
		}
	}
}

在这里插入图片描述

2.5 员工类接口练习

package com.atguigu.test06.exer;

import java.util.Arrays;
/*
(1)声明一个员工类Employee,有属性:编号、姓名、年龄、薪资
(2)让Employee员工类实现java.lang.Comparable接口,
		重写抽象方法,按照编号从小到大排序		
(3)在测试类中创建Employee[]数组,调用java.util.Arrays的sort方法进行排序,遍历结果
(4)声明SalaryComparator类,实现java.util.Comparator接口,
		重写抽象方法,按照薪资从高到低排序
	用SalaryComparator对象重新对Employee[]数组进行排序,遍历结果
*/
public class TestExer2 {
	public static void main(String[] args) {
		Employee[] all = new Employee[3];
		all[0] = new Employee(2, "王小二", 22, 20000);
		all[1] = new Employee(3, "张三", 23, 13000);
		all[2] = new Employee(1, "李四", 24, 8000);		
		//调用java.util.Arrays的sort方法进行排序,遍历结果
		Arrays.sort(all);		
		for (int i = 0; i < all.length; i++) { //按编号id从小到大排序
			System.out.println(all[i]);
		}
		System.out.println("-----------------------------");
		
		//再次调用java.util.Arrays的sort方法进行排序,遍历结果
		Arrays.sort(all, new SalaryComparator());
		for (int i = 0; i < all.length; i++) {
			System.out.println(all[i]);
		}
	}
}
package com.atguigu.test06.exer;
/*
(1)声明一个员工类Employee,有属性:编号、姓名、年龄、薪资
(2)让Employee员工类实现java.lang.Comparable接口,
		重写抽象方法,按照编号从小到大排序
 */
public class Employee implements Comparable{	
	private int id;
	private String name;
	private int age;
	private double salary;
	public Employee(int id, String name, int age, double salary) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.salary = salary;
	}
	public Employee() {
		super();
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	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 double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + "]";
	}	
	//重写抽象方法,按照编号从小到大排序
	@Override
	public int compareTo(Object o) {
		return this.id - ((Employee)o).id;
	}	
}
package com.atguigu.test06.exer;

import java.util.Comparator;
/*
 * (4)声明SalaryComparator类,实现java.util.Comparator接口,
		重写抽象方法,按照薪资从高到低排序
 */
public class SalaryComparator implements Comparator {
	@Override
	public int compare(Object o1, Object o2) {
		Employee e1 = (Employee) o1;
		Employee e2 = (Employee) o2;		
		if(e1.getSalary() > e2.getSalary()){
			return -1;
		}else if(e1.getSalary() < e2.getSalary()){
			return 1;
		}
		return 0;
	}
}

在这里插入图片描述

©️2020 CSDN 皮肤主题: 终极编程指南 设计师:CSDN官方博客 返回首页