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();
}
}
}
总结:对象拷贝的流程
- 默认的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
Consumer
Function<T,R> --- R apply(T t)
BiFunction<T,U,R> --- R apply(T t,U u)
Predicate
注意: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());
}
}