Java面向对象(二)

Java面向对象(二)

1.1 接口(interface)

接口不是类,接口是对类的一组需求的描述。(接口是行为的抽象)

public class Employee implements Comparable<Employee> {
    private String name;
    private double salary;

    public Employee(String name,double salary){
        this.name = name;
        this.salary = salary;
    }

    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;
    }

    public void raiseByPercent(double percent){
    double raise = salary * percent / 100;
    salary += raise;
    }

    @Override
    public int compareTo(Employee other) {
        return Double.compare(salary,other.salary);
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", salary=" + salary +
                '}';
    }
}

public class CompareTest {
    public static void main(String[] args) {
        Employee[] employees = new Employee[2];

        employees[0] = new Employee("YCL",10000);
        employees[1] = new Employee("Tom",10000);


        for (Employee e: employees) {
            System.out.println(e);
        }

        System.out.println(employees[0].compareTo(employees[1]));
    }
}
/**
 * 接口:
 * 1.接口中只能定义静态常量,默认为public static final
 * 2.方法默认为public
 * 3. 1.8之前接口中不允许有实现
 * 4.1.8之后接口可以包含默认方法
 */
public interface Bird {
     void fly();
     void attack();
     //默认方法
    default void doSomething(){
          System.out.println("a");
     }
}
public class NormalBird implements Bird {
    private String color;
    private String name;

    public NormalBird(String color, String name) {
        this.color = color;
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void fly() {
        System.out.println("I can fly");
    }

    @Override
    public void attack() {
        System.out.println("I can't attack..");
    }

    @Override
    public String toString() {
        return "NormalBird{" +
                "color='" + color + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

public class RedBird extends NormalBird implements Bird {

    private String attackModel;

    public RedBird(String color, String name) {
        super(color, name);
        this.attackModel = "normal-attack";

    }

    public String getAttackModel() {
        return attackModel;
    }

    public void setAttackModel(String attackModel) {
        this.attackModel = attackModel;
    }

    @Override
    public void fly() {
        super.fly();
    }

    @Override
    public void attack() {
        System.out.println(attackModel);
    }

    @Override
    public String toString() {
        return "RedBird{" + super.getName() +"," + super.getColor()+ "}";
}
}
public class BlackBird extends NormalBird implements Bird {
    private String attackModel;

    public BlackBird(String color, String name, String attackModel) {
        super(color, name);
        this.attackModel = attackModel;
    }

    @Override
    public void fly() {
        super.fly();
    }

    @Override
    public void attack() {
        System.out.println(this.attackModel);
    }

    @Override
    public String toString() {
        return "BlackBird{" + super.getName() +"," + super.getColor()+ "}";
    }
}
public class BirdTest {
    public static void main(String[] args) {
        NormalBird bird = new NormalBird("white","nor-bird");
        System.out.println(bird);
        bird.fly();
        bird.attack();

        System.out.println("----------------------------------");
        //多态
        NormalBird blackBird = new BlackBird("Black","Black-bird","Boom");
        System.out.println(blackBird);
        blackBird.fly();
        blackBird.attack();

        System.out.println("-----------------------------------");
        //接口变量
        Bird b;
        b = new RedBird("Red","Red-Bird");
        System.out.println(b.toString());
        b.fly();
        b.attack();

//     System.out.println(b.getClass().getName());

        if (bird instanceof Bird){
            System.out.println("bird对象对应的类实现了Bird接口");
        }
    }
}

/**
 * 接口中的public方法在实现类中必须全部重写
 * default方法可以不用重写
 */
public interface InterfaceD {
    void eat();
    default void walk(){
        System.out.println("walk");
    }
}

1.1.1 冲突问题

场景:如果在接口中将一个方法定义为默认方法,然后在父类或者另一个接口中定义了相同的方法。
1.父类优先。如果父类有一个相同的方法(同名,参数也相同)那么默认方法会被忽略。
2.接口冲突。一个父接口提供了默认方法,另一个接口也提供了相同的方法(不管参数是否相同),必须覆盖这个方法来解决。
3.其他,如果一个类实现了一个父类同时实现一个接口,方法名相同(如上面的程序),那么方法只会考虑父类。

1.1.2 接口回调

当某一事件发生时触发的函数.

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;


public class TimeTest {
    public static void main(String[] args) {

        ActionListener listener = new TimePrinter();
        //计时器
        Timer time = new Timer(5000,listener);
        //触发事件,调用回调方法
        time.start();
        //显示提示框
        JOptionPane.showMessageDialog(null,"是否退出程序?");
        System.exit(0);
    }

    static class TimePrinter implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("当前的时间是:" + new Date());
            //响铃
            Toolkit.getDefaultToolkit().beep();
        }
    }
}

1.1.3 对象克隆

对象复制(原型模式)

  • 浅拷贝
public class Employee implements Comparable<Employee>,Cloneable {
    private String name;
    private double salary;

    public Employee(String name,double salary){
        this.name = name;
        this.salary = salary;
    }

    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;
    }

    public void raiseByPercent(double percent){
    double raise = salary * percent / 100;
    salary += raise;
    }

    @Override
    public int compareTo(Employee other) {
        return Double.compare(salary,other.salary);
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", salary=" + salary +
                '}';
    }
}
import com.oop.interfacetest.Employee;

public class CloneTest {
    public static void main(String[] args) throws CloneNotSupportedException {

        Employee original = new Employee("A",1000);
        //copy和original是相同的一个对象
        //Employee copy = original;
        Employee copy = (Employee) original.clone();
        copy.setSalary(100);

        System.out.println(copy);
        System.out.println(original);

    }
}
  • 深拷贝
import java.util.Date;
import java.util.GregorianCalendar;

public class Employee2 implements Cloneable {
    private String name;
    private double salary;
    private Date hireDay;

    public Employee2(String name, double salary) {
        this.name = name;
        this.salary = salary;
        this.hireDay = new Date();
    }

    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;
    }

    public Date getHireDay() {
        return hireDay;
    }

    public void setHireDay(int year,int month,int day) {
        this.hireDay = new GregorianCalendar(year,month-1,day).getTime();
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        //调用object.clone()复制本类
        Employee2 cloned = (Employee2) super.clone();
        //复制本类中的可变对象
        cloned.hireDay = (Date) hireDay.clone();

        return cloned;
    }

    @Override
    public String toString() {
        return "Employee2{" +
                "name='" + name + '\'' +
                ", salary=" + salary +
                ", hireDay=" + hireDay +
                '}';
    }
}
import com.oop.interfacetest.Employee2;

public class DeepCloneTest {
    public static void main(String[] args) {
        try {
            Employee2 original = new Employee2("A",1000);
            original.setHireDay(2020,1,1);
            Employee2 copy = (Employee2) original.clone();
            copy.setHireDay(2020,4,3);
            System.out.println(original);
            System.out.println(copy);
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
        }
    }
}

未命名文件 (1).png

总结:对象拷贝的流程

  • 默认的clone方法是否满足要求 (super.clone())---- 如果满足就是浅拷贝。
  • 是否可以在可变的子对象上调用clone方法来进行修补。
  • 是否不该使用clone方法
  • 如果要进行clone,被复制的类必须实现Cloneable接口。
  • 被复制的类必须重写clone方法,并把访问修饰符改为public。

2.1 lambda表达式简单使用

import java.util.Arrays;
import java.util.Comparator;

public class CompareTest implements Comparator<String> {
    public static void main(String[] args) {
        String[] planets = new String[]{"Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uranus","Neptune"};
        Comparator<String> com = new CompareTest();
        Arrays.sort(planets,com);
        System.out.println(Arrays.toString(planets));
    }

    @Override
    public int compare(String o1, String o2) {
        return o1.length() - o2.length();
    }
}
import java.io.Serializable;
import java.util.Comparator;
import java.util.function.BiFunction;

@FunctionalInterface
public interface MyCompare<T> extends Comparator<T> {
    @Override
    int compare(T o1, T o2);

    public static <T> MyCompare<T> useBi(BiFunction biFunction){
        return (MyCompare<T> & Serializable)
                (s1,s2) -> (Integer) biFunction.apply(s1,s2);
    }
}
import javax.swing.*;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.function.BiFunction;

public class LambdaTest {
    public static void main(String[] args) {
        String[] planets = new String[]{"Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uranus","Neptune"};
        System.out.println(Arrays.toString(planets));
        //根据字典顺序排序
        Arrays.sort(planets);
        System.out.println(Arrays.toString(planets));
        System.out.println("----------------------------------------");
        //根据长度排序
        //编译器会做类型推断
        // y = x
        //(参数) -> 方法体
        //(s1,s2) -> s1.length() - s2.length()
//        Arrays.sort(planets, Comparator.comparingInt(String::length));

        BiFunction<String,String,Integer> compare = (s1,s2) -> s1.length() - s2.length();
        Arrays.sort(planets,MyCompare.useBi(compare));
        System.out.println(Arrays.toString(planets));

        System.out.println("---------------------------------");
//        Timer timer = new Timer(1000, event ->
//                System.out.println("当前的时间是:" + new Date()));
//        timer.start();
//
//        JOptionPane.showMessageDialog(null,"是否退出程序?");
//        System.exit(0);
        Timer timer = new Timer(1000,System.out::println);
        //System.out::println ---> x -> System.out.println(x)
        timer.start();
        JOptionPane.showMessageDialog(null,"是否退出程序?");
        System.exit(0);
        /**
         * this::equals --> x -> this.equals(x)
         */

    }
}
import java.util.function.Function;
import java.util.function.Predicate;

public class Apple {
    private String color;
    private int weight;

    public Apple(String color, int weight) {
        this.color = color;
        this.weight = weight;
    }
    public Apple(){}

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "Apple{" +
                "color='" + color + '\'' +
                ", weight=" + weight +
                '}';
    }

    public static boolean isRedApple(Apple apple){
        return "red".equals(apple.getColor());
    }
    public static boolean isHeavyApple(Apple apple){
        return apple.getWeight() > 100;
    }
    public static Apple selectApple(Apple apple, Predicate<Apple> p){
        if (p.test(apple)){
            return apple;
        }
        return null;
    }



    public static void main(String[] args) {
        Apple apple = new Apple("red",70);
        Apple apple2 = new Apple("green",125);
        System.out.println(selectApple(apple,Apple::isHeavyApple));
        System.out.println(selectApple(apple,Apple::isRedApple));
        Supplier<Apple> supplier = Apple::new;
        Apple apple3 = supplier.get();
        System.out.println(apple3);
        BiFunction<String,Integer,Apple> biFunction = Apple::new;
        Apple apple4 = biFunction.apply("yellow",50);
        System.out.println(apple4);
    }

    /**
     * ::操作符
     * object::instanceMethod
     * Class::staticMethod
     * Class::instanceMethod
     *this::instanceMethod
     *super::instanceMethod
     */
}
import java.util.function.Consumer;
import java.util.function.Supplier;

public class A {
    public String a(){
        return  "A";
    }

    public void aa(String s){
        System.out.println(s);
    }
    public static void main(String[] args) {
        B b = new B();
        b.b();

}


}

class B extends A{
    public void b() {
        Supplier<String> supplier = super::a;
        System.out.println(supplier.get());
        Consumer<String> consumer = super::aa;
        consumer.accept("YCL");
        /**
         *  consumer={
         *   public void aa(String s){
         *         System.out.println(s);
         *     }
         *  }
         */

    }
}

总结:
1.lambda的组成
1) 一个代码块
2)参数
3)自由变量的值
4)->运算符


2.什么时候用lambda
1)接口的抽象方法只有一个,并且有@FunctionalInterface注解时可以使用;
2)针对一些逻辑类似的业务代码,可以使用lambda进行简化


3.常用的函数式接口
Runnable --- run
Supplier --- T get()
Consumer --- accept(T t)
Function<T,R> --- R apply(T t)
BiFunction<T,U,R> --- R apply(T t,U u)
Predicate --- boolean test(T t)
注意:lambda不要过度使用

2.2内部类(inner class)

定义在一个类中的另一个类。
定义内部类的原因:

  • 内部类中--内部类中的方法-->外部类(数据,私有变量)
  • 内部类可以对同一个包中其他类隐藏
  • 定义一个回调函数时,可以使用匿名内部类
  • 静态内部类
    | | 接口(interface) | 抽象类(abstract) |
    | --- | --- | --- |
    | 相同点 | 都存在抽象方法(接口中是类抽象方法) | |
    | 基于定义的不同点 | public类抽象方法,静态常量,default方法,静态方法
    接口之间可以多继承用extends | 抽象方法(除private外,用abstract修饰,原则上抽象方法不是必须的)私有方法,普通方法,静态方法,构造器 变量 抽象类之间可以单继承 |
    | 实现的不同的 | 行为抽象,用implements实现,一个实现类可实现多个接口 | 通用模板的抽象,用estends,一个实现类只能实现一个抽象类 |
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

class ClockControl {
    private int interval;
    private boolean beep;

    public ClockControl(int interval, boolean beep) {
        this.interval = interval;
        this.beep = beep;
    }

    public void start(){
        Timer timer = new Timer(interval,new TimePrinter());
        timer.start();
    }

    /**
     * 在外部类中调用内部类的构造方法
     * this.new InnerClass(xxxx)
     * @return
     */
    public ActionListener callInner(){
        ActionListener listener = this.new TimePrinter(1);
        return listener;
    }

    /**
     * 1.内部类
     */
    public class TimePrinter implements ActionListener {
        private int innerVal;
        /**
         * 内部类中生命的所有静态域都必须是final
         * 内部类中不能有static方法
         */
        private static final int f = 2;

        public TimePrinter(){}

        public TimePrinter(int innerVal) {
            this.innerVal = innerVal;
        }
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("当前时间是:" + new Date());
            //内部类访问外部类的成员变量
            //方式1
//            if (/*outer.*/beep) {
//                Toolkit.getDefaultToolkit().beep();
//            }
            //方式2
            //OuterClass.this
            if (ClockControl.this.beep){
                Toolkit.getDefaultToolkit().beep();
            }
        }
    }
}

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

public class ClockControl2 {
    //全局变量
    private int interval;
    private boolean beep;

    public ClockControl2(int interval, boolean beep) {
        this.interval = interval;
        this.beep = beep;
    }

    /**
     * 参数列表定义的就是局部变量
     * @param interval
     * @param beep
     * 在局部内部类中定义的局部变量,是final的,一旦赋值就没法改变
     */
    public void start(int interval,boolean beep) {
        /**
         * 2.局部内部类
         * 不能用public和private修饰
         * 这个方法只对当前外部类可见
         */
        class TimePrinter implements ActionListener {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("当前时间是:" + new Date());
                //不是外部类的成员变量了
                    if (beep) {
                        Toolkit.getDefaultToolkit().beep();
                    }
            }
        }
        ActionListener listener = new TimePrinter();
        Timer timer = new Timer(interval,listener);
        timer.start();
    }
    /**
     * 访问局部内部类的流程
     * 1.调用start()
     * 2.发现局部内部类,调用局部内部类的构造器,初始化listener对象
     * 3.将listener传递给Timer构造器,然后程序执行,start()结束,局部变量beep销毁
     * 4.执行 actionPerformed(ActionEvent e)方法,执行if(beep),在内部类中会对局部变量进行备份
     */
}
import javax.swing.*;

public class InnerClassTest {
    public static void main(String[] args) {
//        ClockControl clock = new ClockControl(1000,true);
//        //调用内部类的构造方法,在外部类外面
//        //OuterClass.InnerClass xxx = outer.new InnerClass(xxx);
//        ClockControl.TimePrinter timePrinter = clock.new TimePrinter(1);
//        clock.start();

        ClockControl2 cc2 = new ClockControl2(2000,true);
        cc2.start(3000,true);
        JOptionPane.showMessageDialog(null,"是否退出程序?");
        System.exit(0);
    }
}
public class ClockControl3 {
    //全局变量
    private int interval;
    private boolean beep;

    public ClockControl3(int interval, boolean beep) {
        this.interval = interval;
        this.beep = beep;
    }


    public void start(int interval,boolean beep) {
        /**
         * 创建一个实现某某接口的类的新对象,并且定义接口的实现方法
         * new SuperType(xxxx){
         * innerClass method and data
         * }
         * 3匿名类不能有构造器
         */
        ActionListener listener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("当前时间是:" + new Date());
                //不是外部类的成员变量了
                if (beep) {
                    Toolkit.getDefaultToolkit().beep();
                }
            }
        };
        /**
         * ActionListener listener = e -> {
         *             System.out.println("当前时间是:" + new Date());
         *             //不是外部类的成员变量了
         *             if (beep) {
         *                 Toolkit.getDefaultToolkit().beep();
         *             }
         *         };
         */
        Timer timer = new Timer(interval,listener);
        timer.start();
    }
}

/**
 * 可以有构造器,只是不能初始化
 */
public abstract class AbstractClass {
    public AbstractClass(String s){}
    public abstract void method();
}
public class ClassA /*extends AbstractClass*/ {

//    public void test(){
//        AbstractClass abstractClass = new AbstractClass("s") {
//            @Override
//            public void method() {
//                System.out.println("我来自抽象类");
//            }
//        };
          //abstractClass.method();
//    }

    public static void main(String[] args) {
        //这是抽象类的构造器
        AbstractClass abstractClass = new AbstractClass("s") {
            @Override
            public void method() {
                System.out.println("aaa");
            }
        };
        abstractClass.method();
    }
}

//    @Override
//    public void method() {
//        System.out.println("aaa");
//    }
//}
class TwoNums {
    /**
     * 静态内部类
     */
    public static class Pair {
        private double first;
        private double second;

        public Pair(double first, double second) {
            this.first = first;
            this.second = second;
        }

        public double getFirst() {
            return first;
        }


        public double getSecond() {
            return second;
        }

    }
    public static Pair maxMin(double[] val) {
        double min = Double.POSITIVE_INFINITY;
        double max = Double.NEGATIVE_INFINITY;
        for (double d : val) {
            if (min > d) {
                min = d;
            }

            if (max < d) {
                max = d;
            }

        }
        return new Pair(min, max);
    }
}

public class StaticInnerTest {
    public static void main(String[] args) {
        double[] d  = new double[20];
        for (int i = 0; i < d.length ; i++) {
            d[i] = 100 * Math.random();
        }
        //OuterClass.Innerclass x = OuterClass.xxx();
        TwoNums.Pair p = TwoNums.maxMin(d);
        System.out.println("min:" + p.getFirst());
        System.out.println("max:" + p.getSecond());
    }
}
posted @ 2020-07-15 21:49  Dave-Mo  阅读(98)  评论(0)    收藏  举报