面向对象的第三特征是:多态,多态可以理解为事物的多样性,亦可以用一句话概括,父类引用指向子类对象。
1.多态的基本使用(注意:对于方法而言,编译看左边,运行看右边,但对于属性而言,其编译看左边,运行也是看左边,所以多态只适用于方法)
package com.yl.pdfdemo.day05.p1;
/**
* @Author wfj
* @Date 2021/3/30
* @Description
* @Version 1.0
*/
public class Person {
String name;
int age;
int id = 1000;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public Person() {
}
public Person(String name,int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println("Person eat...");
}
public void say() {
System.out.println("Person say...");
}
}
package com.yl.pdfdemo.day05.p1;
/**
* @Author wfj
* @Date 2021/3/30
* @Description
* @Version 1.0
*/
public class Man extends Person {
int grade;
int id = 1001;
public void play() {
System.out.println("Man play....");
}
@Override
public void eat() {
System.out.println("Man eat...");
}
@Override
public void say() {
System.out.println("Man say...");
}
}
package com.yl.pdfdemo.day05.p1;
/**
* @Author wfj
* @Date 2021/3/30
* @Description
* @Version 1.0
*/
public class Woman extends Person{
int height;
public void setHeight(int height) {
this.height = height;
}
public int getHeight() {
return height;
}
public Woman() {}
public Woman(int height) {
this.height = height;
}
public void shopping() {
System.out.println("woman shopping");
}
@Override
public void eat() {
System.out.println("Woman eat...");
}
@Override
public void say() {
System.out.println("Woman say...");
}
}
package com.yl.pdfdemo.day05.p1;
/**
* @Author wfj
* @Date 2021/3/30
* @Description 面向对象第三特征:多态性
* @Version 1.0
*/
public class PersonTest {
public static void main(String[] args) {
/**
* 1.理解多态性:可以理解为一个事物的多种形态
* 2.何为多态性
* 对象的多态性:父类的引用指向子类的对象(或者子类的对象赋给父类的引用)
*
* 3.多态的使用,虚拟方法调用
* 有了对象的多态性以后,我们在编译器,只能调用父类中声明的方法,但在运行的时候,实际执行的是子类中重写父类的方法
*
* 结论::编译看左边,运行看右边
*
* 4.多态性使用前提:
* 1)类的继承关系
* 2)方法的重写
*
* 5.对象的多态性:只适用于方法,不适用于属性(编译看左边,运行看左边)
*/
Person p1 = new Person();
p1.eat();
Man m1 = new Man();
m1.age = 18;
m1.eat();
m1.play();
System.out.println("================================");
// 多态性:父类的引用指向子类的对象
Person p2 = new Man();
// 多态的使用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法 ===虚拟方法调用
p2.eat();
p2.say();
System.out.println(p2.id); // 1000,就近原则,会取父类的id
//p2.play(); 调用报错,因为父类没有这个方法
//结论:编译看左边,运行看右边
Person p3 = new Woman();
p3.eat();
p3.say();
System.out.println("====================================");
//有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法,但是由于变量声明为父类型,导致
//编译时,只能调用父类中声明的属性和方法,子类特有的属性和方法不能调用
//如何才能调用子类持有的属性和方法
// 向下转型,强制类型转换
Man m2 = (Man)p2;
System.out.println(m2.grade);//Man特有的属性
//使用强制类型转换时,可能出现ClassCastException(类型转化异常)
// Woman w1 = (Woman) p2;
// System.out.println(w1.height);
//instanceof关键字的使用
// a instanceof A 判断a是否为A的对象实例,如果是就返回true,否则返回false
//如果a instanceof A 返回true,则a instanceof B也返回true,其中B是A的父类
if (p2 instanceof Man) {
System.out.println("Man...");
}
if (p2 instanceof Woman) {
System.out.println("Woman...");
}
if (p2 instanceof Person) {
System.out.println("Person...");
}
if (p2 instanceof Object) {
System.out.println("Object...");
}
//练习:
//问题一:编译时通过,运行时不通过
// Person p4 = new Woman();
// Man m3 = (Man)p4;//类型转换异常
//编译时通过,运行时不通过
// Person p6 = new Person();
// Man m4 = (Man)p6;
//问题二:编译通过,运行时也通过
Object obj = new Woman();
Person p5 = (Person)obj;
//问题三,编译不通过
//Man m5 = new Woman();
//String str = new Date();
}
}
2.多态使用简单例子
package com.yl.pdfdemo.day05.p1;
import java.sql.Connection;
/**
* @Author wfj
* @Date 2021/3/30
* @Description
* @Version 1.0
*/
public class AnimalTest {
public static void main(String[] args) {
/**
* 多态性的使用例子1
*/
AnimalTest test = new AnimalTest();
test.func(new Dog());
test.func(new Cat());
}
public void func(Animal animal) { // Animal animal = new Dog()
animal.eat();
animal.run();
}
}
class Animal{
public void eat() {
System.out.println("eat....");
}
public void run() {
System.out.println("run...");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("dog eat()....");
}
@Override
public void run() {
System.out.println("dog run()...");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("cat eat()....");
}
@Override
public void run() {
System.out.println("cat run()...");
}
}
// 举例2
class Order{
public void call(Object obj){
}
}
// 举例3
class Driver{
public void getCon(Connection con) { // con = new MysqlConnection
}
}
3.多态练习
1)
package com.yl.pdfdemo.day05.p1;
/**
* @Author wfj
* @Date 2021/4/8
* @Description
* @Version 1.0
*/
public class GeometricObject {
protected String color;
protected double weight;
public void setColor(String color) {
this.color = color;
}
public String getColor() {
return color;
}
public void setWeight(double weight) {
this.weight = weight;
}
public double getWeight() {
return weight;
}
public GeometricObject() {
}
public GeometricObject(String color,double weight) {
this.color = color;
this.weight = weight;
}
public double findArea() {
return 0.0;
}
}
package com.yl.pdfdemo.day05.p1;
/**
* @Author wfj
* @Date 2021/4/8
* @Description
* @Version 1.0
*/
public class Circle extends GeometricObject {
private double radius;
public void setRadius(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
public Circle() {
}
public Circle(double radius,String color,double weight) {
super(color,weight);
this.radius = radius;
}
@Override
public double findArea() {
return Math.PI * radius * radius;
}
}
package com.yl.pdfdemo.day05.p1;
/**
* @Author wfj
* @Date 2021/4/8
* @Description
* @Version 1.0
*/
public class MyRectangle extends GeometricObject {
private double width;
private double height;
public void setWidth(double width) {
this.width = width;
}
public double getWidth() {
return width;
}
public void setHeight(double height) {
this.height = height;
}
public double getHeight() {
return height;
}
public MyRectangle() {
}
public MyRectangle(double width,double height,String color,double weight) {
super(color,weight);
this.height = height;
this.width = width;
}
@Override
public double findArea() {
return width * height;
}
}
package com.yl.pdfdemo.day05.p1;
/**
* @Author wfj
* @Date 2021/4/8
* @Description 多态练习2
* @Version 1.0
*/
public class GeometricTest {
public static void main(String[] args) {
GeometricTest test = new GeometricTest();
Circle c1 = new Circle(2.3,"白色",1);
test.display(c1);
Circle c2 = new Circle(5.6,"红褐色",2);
test.display(c2);
boolean b = test.compareArea(c1, c2);
System.out.println("c1与c2面积是否相等:"+b);
MyRectangle rectangle = new MyRectangle(10,20,"米其色",3);
test.display(rectangle);
}
public void display(GeometricObject o) {
System.out.println("面积为:" + o.findArea());
}
public boolean compareArea(GeometricObject o1,GeometricObject o2) {
return o1.findArea() == o2.findArea();
}
}
2)
package com.yl.pdfdemo.day05.p1;
/**
* @Author wfj
* @Date 2021/4/8
* @Description 多态练习2
* @Version 1.0
*/
public class InstanceTest {
public static void main(String[] args) {
InstanceTest test = new InstanceTest();
test.method(new Car());
}
public void method(Transport t) {
String info = t.getInfo();
System.out.println(info);
if (t instanceof Bus) {
System.out.println("transport...");
System.out.println("car...");
System.out.println("bus...");
} else if (t instanceof Car) {
System.out.println("transport...");
System.out.println("car...");
} else {
System.out.println("transport");
}
}
}
class Transport{
protected String name = "transport";
protected int price = 10000;
public String getInfo() {
return "Name:" + name + "\nPrice:" + price;
}
}
class Car extends Transport{
protected String banner = "benzip";
public String getInfo() {
return "Name:" + name + "\nPrice:" + price + "\nBanner:" + banner;
}
}
class Bus extends Car {
public Integer sitNumber = 20;
public String getInfo() {
return "Name:" + name + "\nPrice:" + price + "\nBanner:" + banner + "\nSitNumber:" + sitNumber;
}
}
3)
package com.yl.pdfdemo.day05.p1;
/**
* @Author wfj
* @Date 2021/4/8
* @Description 多态练习1
* @Version 1.0
*/
public class FieldMethodTest {
public static void main(String[] args) {
/**
* 结论:
* 1.若子类重写了父类的方法,就意味着子类定义的方法彻底覆盖了父类里的同名方法
* 系统不可能把父类里的方法转移到子类:编译看左边,运行看右边
*
* 2.对于实例变量则不存在这样的现象,即使子类定义了与父类完全相通的实例变量,这个实例变量
* 依然不会覆盖父类中的实例变量:编译运行都看左边
*/
Sub s = new Sub();
System.out.println(s.count);//20
s.display();//20
Base b = s;//多态性
//==对于引用数据类型来讲,比较的是两个地址值
System.out.println(b == s);//true
System.out.println(b.count);//10
b.display();//20
}
}
class Base{
int count = 10;
public void display() {
System.out.println(this.count);
}
}
class Sub extends Base {
int count = 20;
@Override
public void display() {
System.out.println(this.count);
}
}
4)
package com.yl.pdfdemo.day05.p1;
/**
* @Author wfj
* @Date 2021/4/8
* @Description 多态面试题1
* @Version 1.0
*/
public class InterviewTest1 {
public static void main(String[] args) {
Base1 base1 = new Sub1();
base1.add(1,3,5); // sub1...
Sub1 sub1 = (Sub1) base1;
sub1.add(1,3,5); // sub12....
}
}
class Base1 {
public void add(int a,int ...arr) {
System.out.println("base1...");
}
}
class Sub1 extends Base1 {
// int ...arr实际上和int[] arr一样,所以add方法和父类的构成了重写
@Override
public void add(int a,int[] arr) {
System.out.println("sub1...");
}
public void add(int a,int b,int c) {
System.out.println("sub12...");
}
}
4.Object类介绍
package com.yl.pdfdemo.day05.p2;
import com.sun.org.apache.xpath.internal.operations.Or;
/**
* @Author wfj
* @Date 2021/4/8
* @Description java.lang.Object类
* @Version 1.0
*/
public class ObjectTest {
public static void main(String[] args) {
/**
* 1.Object是所有类的根父类
* 2.如果在类的声明中未使用extends继承某一个类,则默认继承Object类
* 3.Object中的属性和方法
* 属性:
* 没有声明属性
* 方法:
* equals(),toString(),getClass(),hashCode(),clone(),finalize(),wait(),notify(),notifyAll()
*/
Order1 order1= new Order1();
System.out.println(order1.getClass().getSuperclass());
}
}
class Order1{
}
5.equals关键字
1)基本使用
package com.yl.pdfdemo.day05.p2;
/**
* @Author wfj
* @Date 2021/4/8
* @Description ==与equals的面试题
* @Version 1.0
*/
public class EqualTest {
public static void main(String[] args) {
/**
* ==与equals的区别:
* 一、==:为运算符
* 1.可以使用在基本数据类型变量和引用数据类型变量中
* 2.如果比较的是基本数据类型变量,比较两个变量保存的值是否相等(不一定要类型相等)
* 如果比较是的引用数据类型变量,比较的是两个地址值是否相同
* 补充:==符号使用时,必须保证符号左右的变量类型一致
*
* 二、eauals()
* 1.是一个方法,而不是运算符
* 2.只适用于引用数据类型
* 3.Object中equals()的定义
* public boolean eauals(Object o) {
* return (this == o);
* }
* 说明:Object类中定义的equals()和==作用相同,比较两个对象的地址值是否相同,即是否指向同一个对象
* 4.像String,Date,File,包装类等都重写了Object类中的equals方法,重写后,比较的不是两个对象的地址值,而是两个对象实体内容是否相同
*
* 5.通常情况下,我们自定义的类如果使用equals的话,通常都是比较两个对象实体内容的是否相同,
* 那么我们就需要重写Object类的equals方法
*/
int i = 10;
int j = 10;
double d = 10.0;
System.out.println(i == j); // true
System.out.println(i == d); // true,自动类型提升,int会转为double再来比较
boolean b = true;
// System.out.println(i == b); 不能和布尔类型的比较
char c = 10;
System.out.println(i == c);// true
char c1 = 'A';
char c2 = 65;
System.out.println(c1 == c2); // true
Fruit f1 = new Fruit("苹果",11);
Fruit f2 = new Fruit("苹果",11);
System.out.println(f1 == f2); //false
String str = new String("小明");
String str1 = new String("小明");
System.out.println(str == str1);// false
System.out.println("================");
System.out.println(f1.equals(f2));//true
//String 重写了equals方法
System.out.println(str.equals(str1));//true
}
}
class Fruit{
private String color;
private int age;
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Fruit() {
}
public Fruit(String color, int age) {
this.color = color;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Fruit) {
Fruit f = (Fruit)obj;
if (this.age == f.age && this.color.equals(f.color)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
}
2)练习1
package com.yl.pdfdemo.day05.p2;
/**
* @Author wfj
* @Date 2021/4/8
* @Description
* @Version 1.0
*/
public class GeometricObject {
protected String color;
protected double weight;
public void setColor(String color) {
this.color = color;
}
public String getColor() {
return color;
}
public void setWeight(double weight) {
this.weight = weight;
}
public double getWeight() {
return weight;
}
public GeometricObject() {
this.color = "white";
this.weight = 1.0;
}
public GeometricObject(String color, double weight) {
this.color = color;
this.weight = weight;
}
public double findArea() {
return 0.0;
}
}
package com.yl.pdfdemo.day05.p2;
/**
* @Author wfj
* @Date 2021/4/8
* @Description
* @Version 1.0
*/
public class Circle extends GeometricObject {
private double radius;
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public Circle() {
super();
}
public Circle(double radius) {
super();
this.radius = radius;
}
public Circle(double radius,String color,double weight) {
super(color,weight);
this.radius = radius;
}
@Override
public double findArea() {
return Math.PI * radius * radius;
}
// 比较半径是否相等
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Circle) {
Circle circle = (Circle)obj;
return this.radius == circle.radius;
}
return false;
}
@Override
public String toString() {
return "Circle{" +
"radius=" + radius +
'}';
}
}
package com.yl.pdfdemo.day05.p2;
/**
* @Author wfj
* @Date 2021/4/8
* @Description
* @Version 1.0
*/
public class CircleTest {
public static void main(String[] args) {
Circle circle1 = new Circle(2.3);
Circle circle2 = new Circle(2.3,"white",2.0);
System.out.println("颜色是否相等:" + circle1.getColor().equals(circle2.getColor()));
System.out.println("半径是否相同:" + circle1.equals(circle2));
System.out.println(circle1);
System.out.println(circle1.toString());
}
}
3)练习2
package com.yl.pdfdemo.day05.p2;
import org.springframework.core.annotation.Order;
/**
* @Author wfj
* @Date 2021/4/8
* @Description equals练习
* @Version 1.0
*/
public class OrderTest {
public static void main(String[] args) {
PurchaseOrder order1 = new PurchaseOrder(1,"Apple");
PurchaseOrder order2 = new PurchaseOrder(2,"Banana");
PurchaseOrder order3 = new PurchaseOrder(2,"Banana");
System.out.println(order1.equals(order2));//false
System.out.println(order2.equals(order3));//true
//我们打打印一个对象时,实际上调用了Object的toString方法
//System.out.println(order1);//com.yl.pdfdemo.day05.p2.PurchaseOrder@30f39991,类名+地址值
System.out.println(order1);//重写toString方法后,PurchaseOrder{orderId=1, name='Apple'}
}
}
class PurchaseOrder {
private int orderId;
private String name;
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public PurchaseOrder() {
}
public PurchaseOrder(int orderId, String name) {
this.orderId = orderId;
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof PurchaseOrder) {
PurchaseOrder order = (PurchaseOrder)obj;
return this.orderId == order.orderId && this.name.equals(order.name);
}
return false;
}
@Override
public String toString() {
return "PurchaseOrder{" +
"orderId=" + orderId +
", name='" + name + '\'' +
'}';
}
}
6.包装类的介绍
1)包装类与基本数据类型与String类型相互转换
package com.yl.pdfdemo.day05.p2;
import org.junit.Test;
/**
* @Author wfj
* @Date 2021/4/9
* @Description 包装类的使用
* @Version 1.0
*/
public class WrapperTest1 {
/**
* 包装类的使用:
* 1.java提供了8种基本数据类型对应的包装类,使得基本数据类型的变量具有类的特征
* byte => Byte, shot => Short, int => Integer, long => Long,float => Float,double => Double,boolean => Boolean
* char => Character
*2.要掌握基本数据类型,包装类,和String三者的转换
*/
//基本数据类型 =》包装类,调用包装类的构造器
@Test
public void test1() {
int num1 = 10;
Integer i1 = new Integer(num1);
System.out.println(i1.toString());
Integer i2 = new Integer("123");
System.out.println(i2);
Float f1 = new Float(12.3);
Float f2 = new Float(12.3f);
System.out.println(f1);
System.out.println(f2);
Boolean b1 = new Boolean(true);
Boolean b2 = new Boolean("TrUe");
System.out.println(b2);
Boolean b3 = new Boolean("true12322");
System.out.println(b3);
}
//包装类 => 基本数据类型,调用xxxValue
@Test
public void test2() {
Integer i1 = new Integer(23);
int i = i1.intValue();
System.out.println(i + 1);
Float f1 = new Float("12.9");
float f2 = f1.floatValue();
System.out.println(f2);
}
// jdk5新特性:自动拆箱 自动装箱
@Test
public void test3() {
int i = 13;
//自动装箱,基本数据类型 =》 包装类的对象
show(i);
//自动装箱,基本数据类型 =》 包装类的对象
int num1 = 100;
Integer num2 = num1;
boolean b1 = true;
Boolean b2 = b1;
//自动拆箱,包装类的对象 => 基本数据类型
int num3 = num2;
System.out.println(num3);
}
public void show(Object o) {
System.out.println(o);
}
// 基本数据类型,包装类 =》String,调用String重载的valueOf(XXXX)
@Test
public void test4() {
int num1 = 11;
//方式一:连接运算
String s1 = num1 + "";
//方式二:调用String的valueOf
float f1 = 12.9f;
String s2 = String.valueOf(12.9);
Double d1 = new Double(10.0);
String s3 = String.valueOf(d1);
System.out.println(s2);
System.out.println(s3);
}
//String => 基本数据类型,包装类,调用包装类的parseXXX方法
@Test
public void test5() {
String s1 = "123";
int num1 = Integer.parseInt(s1);
System.out.println(num1 + 1);
String s2 = "true";
boolean b = Boolean.parseBoolean(s2);
System.out.println(b);
}
}
2)包装类面试题
package com.yl.pdfdemo.day05.p2;
import org.junit.Test;
/**
* @Author wfj
* @Date 2021/4/9
* @Description 包装类的面试题
* @Version 1.0
*/
public class WrapperInterview {
@Test
public void test1() {
// 注意,三元运算符,左右两边,数据类型要一致,所以一下Integer自动转换成了Double
Object o1 = true ? new Integer(1) : new Double(2.0);
System.out.println(o1); //1.0
}
@Test
public void test2() {
Object o2;
if (true) {
o2 = new Integer(1);
} else {
o2 = new Double(2.0);
}
System.out.println(o2);//1
}
@Test
public void test3() {
Integer i1 = new Integer(1);
Integer i2 = new Integer(1);
System.out.println(i1 == i2);//false
//Integer内部定义了IntegerCache结构,IntegerCache定义了Integer[],保存了从-128~127范围的整数,
// 如果我们使用自动装箱的方式,给Integer赋值的范围z在-127~128之间,可以直接使用数组中的元素,不用再去new了,目的:提高效率
Integer i3 = 2;
Integer i4 = 2;
System.out.println(i3 == i4);//true
Integer i5 = 128; //new 了一个对象
Integer i6 = 128; // new 了一个对象
System.out.println(i5 == i6);//false
}
}
3)练习(用到了自动拆箱)
package com.yl.pdfdemo.day05.p2;
import java.util.Scanner;
import java.util.Vector;
/**
* @Author wfj
* @Date 2021/4/9
* @Description 包装类练习
* @Version 1.0
*/
public class ScoreTest {
public static void main(String[] args) {
//1.实例化Scanner对象,用于键盘获取学生成绩
Scanner sc = new Scanner(System.in);
//2.创建vector对象,Vector v = new Vector(),相当于原来的数组
Vector v = new Vector();
int max = 0;
//3.循环往数组添加元素,输入负数时,退出循环
for (;;) {
System.out.println("请输入学生成绩(负数代表结束)");
int score = sc.nextInt();
if (score < 0) {
break;
}
if (score > 100) {
System.out.println("输入的数据非法,请重新输入");
continue;
}
v.addElement(score); //自动装箱
//获取成绩最大值
if (score > max) {
max = score;
}
}
//遍历数组
char level;
for (int i = 0; i < v.size(); i++) {
Object o = v.elementAt(i);
Integer inScore = (Integer)o;
int score = inScore.intValue();
if (max - score <= 10) {
level = 'A';
} else if (max - score <= 20) {
level = 'B';
} else if (max - score <= 30) {
level = 'C';
} else {
level = 'D';
}
System.out.println("学生"+ i + "成绩为:" + score + "评分为:" + level);
}
}
}
7.static的使用
1)基本使用
package com.yl.pdfdemo.day05.p3;
/**
* @Author wfj
* @Date 2021/4/13
* @Description static关键字的使用
* @Version 1.0
*/
public class StaticTest {
public static void main(String[] args) {
/**
* 1.static:静态的
* 2.static可以修饰:属性,方法代码块,内部类
*
* 3.使用static修饰属性:静态变量(类变量)
* 3.1 属性,按是否使用static修饰,又分为:静态属性 vs 非静态属性(实例变量)
* 实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性,当修改其中某一个对象的属性时,
* 不会导致其他对象属性也跟着改变
*
* 静态变量:我们创建了多个实例对象,多个对象共享同一个静态变量,当通过一个对象去修改静态变量的值时
* ,其他对象再调用该静态变量,其值也会跟着改变
* 3.2 static属性说明:
* 1)静态变量随着类的加载而加载,可以通过"类.静态变量"的方式进行调用
* 2)静态变量的加载早于对象的创建
* 3)由于类只加载一次,则静态变量在内存中也只会存在一份,存在方法区的静态域中
*
* 类变量 实例变量(能否调用变量)
* 类 yes no
* 对象 yes yes
*
*
*
* 4.使用static修饰方法,静态方法
* 1)随着类的加载而加载,可以通过"类.静态方法"的方式进行调用
* 2)
* 静态方法 非静态方法(能否调用)
* 类 yes no
* 对象 yes yes
* 3)静态方法中,只能调用静态的方法或属性(因为其随着类的加载而加载,在对象没创建之前就加载了,无法调用非静态资源)
* 非静态方法中,既可以调用静态的属性或方法,也可以调用非静态的属性或方法
*
* 5.static注意点:
* 在静态的方法内,不能使用this,super关键字
*
* 6.开发中,如何确定一个属性是否要声明为static
* 》属性是可以被多个对象共享的,不会随着对象的不同而不同的
* 》类中的常量也常声明为static
*
* 开发中,如何确定一个方法是否声明为static
* 》操作静态属性的方法,通常设置为static
* 》工具类的方法,没必要new对象
*
* 注意: 对于 public static void main(String[] args)这个方法,能不能拿到args数组的值呢?
* 答案是可以的,以命令行的方式运行,java 类名 "值1" "值2" "值3",这样从args数组里就可以取到数据了
*/
Chinese.nation = "CNN";
Chinese c1 = new Chinese();
c1.age = 15;
c1.name = "xiaoming";
c1.nation = "CN";
c1.say();
Chinese c2 = new Chinese();
c2.age = 19;
c2.name = "xiaobai";
System.out.println(c1.nation);
System.out.println(c2.nation);
//类.方法名,直接调用静态方法
Chinese.speak();
}
}
class Chinese{
String name;
int age;
static String nation;
public void say() {
//对于非静态方法而言,其可以调用非静态资源
this.show();
System.out.println("say...");
//也可以调用静态资源
walk();
}
public void show() {
System.out.println("name="+name+",age="+age);
}
public static void speak() {
//对于静态方法而言,其不能调用非静态资源
// say();
// name = "shiwei";
//只能调用静态资源
walk();
System.out.println("speak...");
}
public static void walk() {
System.out.println("walk...");
}
}
2)练习1
package com.yl.pdfdemo.day05.p3;
/**
* @Author wfj
* @Date 2021/4/13
* @Description
* @Version 1.0
*/
public class Account {
private int id;
private String password;
private double balance;
private static double interestRate;
private static double minMoney = 1.0;
private static int init = 1001;//用于自动生成id
public Account(){
password = "00000";
id = init++;
}
public Account(String password,double balance) {
id = init++;
this.password = password;
this.balance = balance;
}
public int getId() {
return id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public double getBalance() {
return balance;
}
public static double getInterestRate() {
return interestRate;
}
public static void setInterestRate(double interestRate) {
Account.interestRate = interestRate;
}
public static double getMinMoney() {
return minMoney;
}
public static void setMinMoney(double minMoney) {
Account.minMoney = minMoney;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", password='" + password + '\'' +
", balance=" + balance +
'}';
}
}
package com.yl.pdfdemo.day05.p3;
/**
* @Author wfj
* @Date 2021/4/13
* @Description static练习
* @Version 1.0
*/
public class AccountTest {
public static void main(String[] args) {
Account account1 = new Account();
Account account2 = new Account("666abc",2000.0);
System.out.println(account1);
System.out.println(account2);
}
}
3)练习2
package com.yl.pdfdemo.day05.p3;
/**
* @Author wfj
* @Date 2021/4/13
* @Description 类的成员之四:代码块(或初始化块)
* @Version 1.0
*/
public class BlockTest {
public static void main(String[] args) {
/**
* 1.代码块的作用:用来初始化类,对象
* 2.代码块如果有修饰的话,只能使用static
* 3.分类,静态代码块 vs 非静态代码块
*
* 4.静态代码块
* > 内部可以有输出语句
* > 随着类的加载而执行,而且只执行一次
* > 作用:初始化类的信息
* > 如果我们在一个类中声明了多个static代码块,那么执行顺序和代码的先序顺序一样
* > 静态代码块执行优先于非静态代码块
* > 静态代码块内只能调用静态属性或者静态方法,不可以调用非静态属性或者非静态方法
*
* 5.非静态代码块
* > 内部可以有输出语句
* > 随着对象的加载而执行,每创建一个对象,就执行一次
* > 作用:可以在创建对象时,对对象的的属性进行初始化
* > 如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
* > 非静态代码块就可以调用静态属性或者静态方法,也可以调用非静态属性或者非静态方法
*
*对属性可以赋值的位置:
* 1)默认初始化
* 2)显示初始化
* 3)构造器中初始化
* 4)有了对象以后,通过,对象.属性或者对象.方法的形式,进行赋值
* 5)在代码块中赋值
*/
String desc = Person.desc;
Person p1 = new Person();
Person p2 = new Person();
System.out.println(p2.age);
System.out.println(desc);
}
}
class Person{
String name;
int age;
static String desc = "default";
//static代码块
static {
desc = "staticDesc";
System.out.println("static block1...");
}
static {
desc = "staticDesc";
// 调用静态资源
run();
//不可以调用非静态资源
// name = "小安";
System.out.println("static block2...");
}
//非static代码块
{
//调用非静态资源
age = 1;
name = "小明";
//调用静态资源
run();
System.out.println("block...");
}
public Person() {
}
public Person(String name,int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println("eat...");
}
public static void run() {
System.out.println("run...");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
4)练习3
package com.yl.pdfdemo.day05.p3;
/**
* @Author wfj
* @Date 2021/4/13
* @Description static练习
* @Version 1.0
*/
public class CircleTest {
public static void main(String[] args) {
Circle c1 = new Circle();
Circle c2 = new Circle();
System.out.println("c1的id为:"+c1.getId());
System.out.println("c2的id为:"+c2.getId());
System.out.println("圆个数:"+Circle.getTotal());
}
}
class Circle{
private double radius;
private int id;
private static int total;//记录创建的圆的个数
private static int init = 1001; //被所有对象共享
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public static int getTotal() {
return total;
}
public Circle() {
id = init++;
total++;
}
public double findArea() {
return Math.PI * radius * radius;
}
}
5)练习4
package com.yl.pdfdemo.day05.p3;
/**
* @Author wfj
* @Date 2021/4/13
* @Description 静态代码块练习
* @Version 1.0
*/
class Father {
static {
System.out.println("111");
}
{
System.out.println("222");
}
public Father() {
System.out.println("333");
}
}
public class Son extends Father{
static {
System.out.println("444");
}
{
System.out.println("555");
}
public Son() {
System.out.println("666");
}
public static void main(String[] args) {
/**
* 结果
* 111
* 444
* 777
* *********
* 222
* 333
* 555
* 666
* *************
* 222
* 333
* 555
* 666
* **************
* 222
* 333
*/
System.out.println("777");
System.out.println("*********");
new Son();
System.out.println("*************");
new Son();
System.out.println("**************");
new Father();
}
}
6)练习5
package com.yl.pdfdemo.day05.p3;
/**
* @Author wfj
* @Date 2021/4/13
* @Description 静态代码块练习,总结:由父及子,静态先行
* @Version 1.0
*/
public class LeafTest {
public static void main(String[] args) {
new Leaf();
/**
* Root static block...
* Mid static block...
* Leaf static block...
* Root Normal block...
* Root no args constructor...
* Mid Normal block...
* Mid no args constructor...
* Mid have a arg and arg is:qingfenga
* Leaf Normal block...
* Leaf no arg constructor
*/
System.out.println();
new Leaf();
/**
* Root Normal block...
* Root no args constructor...
* Mid Normal block...
* Mid no args constructor...
* Mid have a arg and arg is:qingfenga
* Leaf Normal block...
* Leaf no arg constructor
*/
}
}
class Root {
static {
System.out.println("Root static block...");
}
{
System.out.println("Root Normal block...");
}
public Root() {
super();
System.out.println("Root no args constructor...");
}
}
class Mid extends Root{
static {
System.out.println("Mid static block...");
}
{
System.out.println("Mid Normal block...");
}
public Mid() {
super();
System.out.println("Mid no args constructor...");
}
public Mid(String msg) {
this();
System.out.println("Mid have a arg and arg is:" + msg);
}
}
class Leaf extends Mid {
static {
System.out.println("Leaf static block...");
}
{
System.out.println("Leaf Normal block...");
}
public Leaf() {
super("qingfenga");
System.out.println("Leaf no arg constructor");
}
}
7)练习6
package com.yl.pdfdemo.day05.p3;
/**
* @Author wfj
* @Date 2021/4/14
* @Description 属性赋值的顺序
* @Version 1.0
*/
public class OrderTest {
public static void main(String[] args) {
/**
* *对属性可以赋值的位置:
* * 1)默认初始化
* * 2)显示初始化
* * 3)构造器中初始化
* * 4)有了对象以后,通过,对象.属性或者对象.方法的形式,进行赋值
* * 5)在代码块中赋值
*
* 顺序:1 -》2 / 5 》3 》 4
*/
//情况1,Order类里声明顺序,声明在前面的先执行
// int id = 10;
// {
// id = 20;
// }
Order order = new Order();
System.out.println(order.id); //20
//情况2
// {
// id = 20;
// }
// int id = 10;
Order order1 = new Order();
System.out.println(order1.id); //10
}
}
class Order{
int id = 10;
{
id = 20;
}
}
8.final关键字
1)基本使用
package com.yl.pdfdemo.day05.p3;
/**
* @Author wfj
* @Date 2021/4/14
* @Description final关键字
* @Version 1.0
*/
public class FinalTest {
public static void main(String[] args) {
/**
* final:最终的
* 1.final可以修饰的结构:类,方法,变量
* 2.final修饰一个类,表示该类不可以被继承
* 比如:String类,System类,StringBuffer类
* 3.final用来修饰方法表明此方法不可以被重写
* 比如:Object类中getClass()方法
* 4.final用来修饰变量:此时的变量就称为是一个常量
* 4.1.final修饰属性:可以考虑赋值的位置有:显式初始化,代码块中初始化,构造器中初始化
* 4.2.final修饰局部变量:
* 尤其是使用final修饰形参时,表明形参是一个常量,当我们调用此方法时,给常量形参赋一个实参,一旦赋值以后
* 就只能在方法内使用此形参,但不能进行重新赋值
* static final 修饰属性 =》全局常量
*/
}
final int WIDTH = 0;
final int LEFT;
final int RIGHT;
{
LEFT = 1;
}
public FinalTest() {
RIGHT = 2;
}
public FinalTest(int n) {
RIGHT = n;
}
public void show() {
final int num = 18;
//不能修改
//num += 1;
}
public void show(final int num) {
//编译不通过,num值不可以修改
//num = 20;
System.out.println(num);
}
}
2)面试题
package com.yl.pdfdemo.day05.p3;
/**
* @Author wfj
* @Date 2021/4/15
* @Description final面试题
* @Version 1.0
*/
public class FinalInterivewTest {
public static void main(String[] args) {
FinalInterivewTest test = new FinalInterivewTest();
Fruit fruit = new Fruit();
test.change(fruit);
}
public int addOne(final int x) {
//编译错误,不能改变x的值
//return ++x;
return x + 1;
}
public void change(final Fruit fruit) {
//编译报错,fruit的地址值不能改变
//fruit = new Fruit();
fruit.id++;
}
}
class Fruit {
int id;
}
9.单例设计模式
- 饿汉方式
package com.yl.pdfdemo.day05.p3;
/**
* @Author wfj
* @Date 2021/4/13
* @Description 单例设计模式:饿汉式
* @Version 1.0
*/
public class SingletonTest1 {
public static void main(String[] args) {
/**
* 1。所谓类的单例设计模式,就是采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例
*
* 2.如何实现?
*
* 3.懒汉式和饿汉式的区别
* 饿汉式:
* 坏处:对象加载时间过长
* 好处:线程安全
* 懒汉式:
* 坏处:线程不安全
* 好处,延迟对象的创建
*/
Bank b1 = Bank.getInstance();
Bank b2 = Bank.getInstance();
System.out.println(b1 == b2);//true
}
}
class Bank{
//1.私有化构造器
private Bank() {
}
//2.内部创建类的对象
private static Bank instance = new Bank();
//3.提供公共的静态方法,返回对象
public static Bank getInstance() {
return instance;
}
}
2)懒汉方式
package com.yl.pdfdemo.day05.p3;
/**
* @Author wfj
* @Date 2021/4/13
* @Description 单例设计模式:懒汉式
* @Version 1.0
*/
public class SingletonTest2 {
public static void main(String[] args) {
Cat c1 = Cat.getInstance();
Cat c2 = Cat.getInstance();
System.out.println(c1 == c2);//true
}
}
class Cat{
//私有化构造器
private Cat() {
}
//创建对象
private static Cat cat = null;
//声明方法
public static Cat getInstance() {
if (cat == null) {
cat = new Cat();
}
return cat;
}
}
10.abstract关键字
1)基本使用
package com.yl.pdfdemo.day05.p4;
import com.yl.pdfdemo.day04.p1.Creature;
/**
* @Author wfj
* @Date 2021/4/15
* @Description abstract关键字
* @Version 1.0
*/
public class AbstractTest {
public static void main(String[] args) {
/**
* abstract:抽象的
* 1.abstract可以修饰的结构:类,方法
* 2.abstract修饰类:抽象类
* > 此类不能实例化
* > 抽象类中一定有构造器,便于子类实例化时调用
* > 开发中,都会提供抽象类的子类,让子类对象实例化,完成相关操作
*
* 3.abstract修饰方法:抽象方法
* > 抽象方法只有方法的声明,没有方法体
* > 包含抽象方法的类,一定是抽象类,反之,抽象类中可以没有抽象方法
* > 若子类重写了父类中所有的抽象方法,方可实例化
* > 若子类没有重写父类中所有的抽象方法,则此类也是一个抽象类,用abstract修饰
*
* abstract使用注意点:
* 1)abstract不能修饰属性,构造器登
* 2)abstract不能修饰私有方法,静态方法,final修饰的方法,final修饰的类
*/
//抽象类不可以实例化
//Person p1 = new Person();
}
}
abstract class Bios{
public abstract void study();
}
abstract class Person extends Bios {
String name;
int age;
public Person() {
}
public Person(String name,int age) {
this.name = name;
this.age =age;
}
//不是抽象方法
// public void say();
//抽象方法
public abstract void say();
public void eat() {
System.out.println("eat...");
}
public void run() {
System.out.println("run...");
}
}
class Student extends Person {
@Override
public void say() {
System.out.println("Student say...");
}
@Override
public void study() {
System.out.println("Student study...");
}
}
2)抽象类的匿名子类
package com.yl.pdfdemo.day05.p4;
/**
* @Author wfj
* @Date 2021/4/15
* @Description 抽象类的匿名子类
* @Version 1.0
*/
public class AnimalTest {
public static void main(String[] args) {
// 创建了一个匿名子类的对象 animal
// Animal animal = new Animal() {
// @Override
// public void eat() {
// System.out.println("匿名对象eat...");
// }
//
// @Override
// public void run() {
// System.out.println("匿名对象run...");
// }
// };
// AnimalTest test = new AnimalTest();
// test.show(animal);
//另外一种写法
AnimalTest test = new AnimalTest();
test.show(new Animal() {
@Override
public void eat() {
System.out.println("匿名对象eat...");
}
@Override
public void run() {
System.out.println("匿名对象run...");
}
});
}
public void show(Animal animal) {
animal.eat();
animal.run();
}
}
abstract class Animal {
public abstract void eat();
public abstract void run();
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("cat eat...");
}
@Override
public void run() {
System.out.println("cat run ...");
}
}
3)抽象类的应用:模板方法的设计模式
package com.yl.pdfdemo.day05.p4;
/**
* @Author wfj
* @Date 2021/4/15
* @Description 抽象类的应用:模板方法的设计模式
* @Version 1.0
*/
public class TemplateTest {
public static void main(String[] args) {
Template template = new SubTemplate();
template.spendTime();
}
}
abstract class Template {
public void spendTime() {
long start = System.currentTimeMillis();
code(); //不确定的部分
long end = System.currentTimeMillis();
System.out.println("共花费了:"+(end - start)+"毫秒");
}
public abstract void code();
}
class SubTemplate extends Template{
//求质数
@Override
public void code() {
for (int i = 2; i <= 1000; i++) {
boolean flag = true;
for (int j = 2; j <= Math.sqrt(i); j++) {
if (i % j == 0) {
flag = false;
break;
}
}
if (flag) {
System.out.println(i);
}
}
}
}
4)练习1
package com.yl.pdfdemo.day05.p4;
/**
* @Author wfj
* @Date 2021/4/15
* @Description
* @Version 1.0
*/
public abstract class Employee {
private String name;
private int id;
private double salary;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Employee() {
super();
}
public Employee(String name, int id, double salary) {
this.name = name;
this.id = id;
this.salary = salary;
}
public abstract void work();
}
package com.yl.pdfdemo.day05.p4;
/**
* @Author wfj
* @Date 2021/4/15
* @Description
* @Version 1.0
*/
public class Manager extends Employee {
private double bonus; //奖金
public Manager(double bonus) {
super();
this.bonus = bonus;
}
public Manager(String name,int id,double salary,double bonus) {
super(name,id,salary);
this.bonus = bonus;
}
@Override
public void work() {
System.out.println("Manager work...");
}
}
package com.yl.pdfdemo.day05.p4;
/**
* @Author wfj
* @Date 2021/4/15
* @Description
* @Version 1.0
*/
public class CommonEmployee extends Employee {
@Override
public void work() {
System.out.println("CommonEmployee work...");
}
}
package com.yl.pdfdemo.day05.p4;
/**
* @Author wfj
* @Date 2021/4/15
* @Description 抽象练习
* @Version 1.0
*/
public class EmployeeTest {
public static void main(String[] args) {
//多态体现
Employee employee = new Manager(1000.0);
employee.work();
CommonEmployee commonEmployee = new CommonEmployee();
commonEmployee.work();
}
}
5)练习2
package com.yl.pdfdemo.day05.p4;
/**
* @Author wfj
* @Date 2021/4/15
* @Description
* @Version 1.0
*/
public abstract class Digest {
private String name;
private int number;
private MyDate birthday;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public MyDate getBirthday() {
return birthday;
}
public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}
public Digest() {
}
public Digest(String name, int number, MyDate birthday) {
this.name = name;
this.number = number;
this.birthday = birthday;
}
public abstract double buy();
@Override
public String toString() {
return "{" +
"name='" + name + '\'' +
", number=" + number +
", birthday=" + birthday.toDateString() +
'}';
}
}
package com.yl.pdfdemo.day05.p4;
/**
* @Author wfj
* @Date 2021/4/15
* @Description
* @Version 1.0
*/
public class MyDate {
private int year;
private int month;
private int day;
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public MyDate() {
}
public MyDate(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public String toDateString() {
return year + "年" + month + "月" + day + "日";
}
}
package com.yl.pdfdemo.day05.p4;
/**
* @Author wfj
* @Date 2021/4/15
* @Description
* @Version 1.0
*/
public class HourlyDigest extends Digest {
private int wage;
private int hour;
public HourlyDigest(String name,int number,MyDate birthday) {
super(name, number, birthday);
}
public HourlyDigest(String name,int number,MyDate birthday,int wage,int hour) {
super(name, number, birthday);
this.wage = wage;
this.hour = hour;
}
@Override
public double buy() {
return wage * hour;
}
@Override
public String toString() {
return "HourlyDigest{" +
super.toString() +
'}';
}
}
package com.yl.pdfdemo.day05.p4;
/**
* @Author wfj
* @Date 2021/4/15
* @Description
* @Version 1.0
*/
public class SalaryDigest extends Digest {
private double monthlySalary;//月工资
public SalaryDigest(String name,int number,MyDate birthday) {
super(name, number, birthday);
}
public SalaryDigest(String name,int number,MyDate birthday,double monthlySalary) {
super(name, number, birthday);
this.monthlySalary = monthlySalary;
}
@Override
public double buy() {
return monthlySalary;
}
@Override
public String toString() {
return "SalaryDigest{" +
super.toString() +
'}';
}
}
package com.yl.pdfdemo.day05.p4;
import javax.sound.midi.Soundbank;
import java.util.Scanner;
/**
* @Author wfj
* @Date 2021/4/15
* @Description
* @Version 1.0
*/
public class DigestTest {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入月份:");
int month = scanner.nextInt();
Digest[] digests = new Digest[2];
digests[0] = new SalaryDigest("小明",1001,new MyDate(1992,2,2),9000);
digests[1] = new HourlyDigest("雄安",1002,new MyDate(1991,1,1),60,240);
for (int i = 0; i< digests.length; i++) {
System.out.println(digests[i]);
double salary = digests[i].buy();
System.out.println("月工资为:"+salary);
if (month == digests[i].getBirthday().getMonth()) {
System.out.println("奖励100");
}
}
}
}
11.interface
- 接口的基本使用
package com.yl.pdfdemo.day05.p5;
/**
* @Author wfj
* @Date 2021/4/15
* @Description 接口的使用
* @Version 1.0
*/
public class InterfaceTest {
public static void main(String[] args) {
/**
* 接口的使用:
* 1.接口使用interface定义
* 2.java中,接口和类是并列的结构
* 3.如何定义接口:定义接口的成员
* 3.1 jdk7及以前:只能定义全局常量和抽象方法
* > public static final 全局常量,书写时,可以省略public static final
* > public abstract 抽象方法
*
* 3.2 jdk8后,除了能定义全局常量和抽象方法,还可以定义静态方法,默认方法(略)
* 4.接口中,不能定义构造器,意味着接口不能实例化
*
* 5.java开发中,接口通过让类(implements)的方式来使用
* 如果实现类覆盖了接口中所有的抽象方法,则此实现类可以实例化
* 如果实现类没有覆盖接口中所有的抽象方法,则实现类仍然是一个抽象类
*
* 6. java类中可以实现多个接口,弥补了单继承的局限性
* 格式:class A extends B implements C,D,E,F
*
* 7.接口与接口之间,可以继承,而且可以多继承
* 8.接口的具体使用,体现多态性
* 9.接口,实际上可以看作是一种规范
*/
System.out.println(Flyable.MAX_SPEED);
System.out.println(Flyable.MIN_SPEED);
// Plane plane = new Plane();
// plane.fly();
// plane.stop();
Flyable pl = new Plane();
pl.fly();
pl.stop();
}
}
interface Flyable{
//全局常量
public static final int MAX_SPEED = 9000;
int MIN_SPEED = 1; //省略了public static final
//抽象方法
public abstract void fly();
void stop();//省略了public abstract
}
interface Attachable{
void attach();
}
class Plane implements Flyable{
@Override
public void fly() {
System.out.println("plane fly...");
}
@Override
public void stop() {
System.out.println("plane stop...");
}
}
class bullet implements Flyable,Attachable{
@Override
public void fly() {
}
@Override
public void stop() {
}
@Override
public void attach() {
}
}
2)练习1
package com.yl.pdfdemo.day05.p5;
/**
* @Author wfj
* @Date 2021/4/16
* @Description 接口的使用
* @Version 1.0
*/
public class UsbTest {
public static void main(String[] args) {
/**
* 接口:
* 1.接口使用上满足多态性
* 2.接口实际上就是定义了一种规范
*
*/
Computer computer = new Computer();
//1.创建了接口的非匿名实现类的非匿名对象
Flash flash = new Flash();
computer.transform(flash);
//2.创建了接口的非匿名实现类的匿名对象
computer.transform(new Printer());
//3.创建了匿名实现类的非匿名对象
USB phone = new USB() {
@Override
public void start() {
System.out.println("phone start...");
}
@Override
public void stop() {
System.out.println("phone stop...");
}
};
computer.transform(phone);
//4.创建了匿名实现类的匿名对象
computer.transform(new USB() {
@Override
public void start() {
System.out.println("mp3 start...");
}
@Override
public void stop() {
System.out.println("mp3 stop...");
}
});
}
}
class Computer {
public void transform(USB usb) {
usb.start();
System.out.println("具体传输数据的细节");
usb.stop();
}
}
interface USB{
void start();
void stop();
}
class Flash implements USB{
@Override
public void start() {
System.out.println("USB start...");
}
@Override
public void stop() {
System.out.println("USB stop...");
}
}
class Printer implements USB{
@Override
public void start() {
System.out.println("printer start...");
}
@Override
public void stop() {
System.out.println("printer stop...");
}
}
3)练习2
package com.yl.pdfdemo.day05.p5;
/**
* @Author wfj
* @Date 2021/4/16
* @Description
* @Version 1.0
*/
public class SubClassTest {
public static void main(String[] args) {
SubClass subClass = new SubClass();
//通过实现类的对象,可以调用接口中的默认方法
//如果实现类重写了接口中的静态方法,调用时,则调用的是实现类重写后的方法
subClass.method2();
// 如果子类继承的父类和实现的接口中定义了同名同参数的默认方法,而且子类没有重写该方法,则调用该方法时,会调用父类的那个方法(类优先原则)
//如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法
//那么实现类没有重写这个方法时,会报错-》接口冲突
subClass.method3();
//编译出错,接口中定义的静态方法,只能通过接口来调用
//subClass.method1();
CompareA.method1();
}
}
class SubClass extends SuperClass implements CompareA{
@Override
public void method2() {
System.out.println("CompareB:CAR");
}
public void myMethod() {
//调用自己的方法
method2();
//调用父类的方法
super.method3();
//调用接口中的默认方法
CompareA.super.method3();
CompareA.super.method2();
}
}
class SuperClass {
public void method3() {
System.out.println("SUperClass:CCC");
}
}
4)练习3,接口的应用:代理模式
package com.yl.pdfdemo.day05.p5;
/**
* @Author wfj
* @Date 2021/4/16
* @Description 接口的应用:代理模式
* @Version 1.0
*/
public class NetworkTest {
public static void main(String[] args) {
Server server = new Server();
ProxyServer proxyServer = new ProxyServer(server);
proxyServer.browse();
}
}
interface NetWork{
public void browse();
}
// 被代理类
class Server implements NetWork{
@Override
public void browse() {
System.out.println("real server...");
}
}
// 代理类
class ProxyServer implements NetWork{
private NetWork netWork;
public ProxyServer(NetWork netWork) {
this.netWork = netWork;
}
public void check() {
System.out.println("ProxyServer check...");
}
@Override
public void browse() {
check();
netWork.browse();
}
}
5)练习4
package com.yl.pdfdemo.day05.p5;
/**
* @Author wfj
* @Date 2021/4/16
* @Description 接口面试题
* @Version 1.0
*/
public class InterviewTest1 {
}
interface A {
int x = 0;
}
class B{
int x = 1;
}
class C extends B implements A{
public void show() {
//编译报错。x不知道要取类还是接口的
// System.out.println(x);
System.out.println(super.x);
System.out.println(A.x);
}
public static void main(String[] args) {
new C().show();
}
}
6)练习5
package com.yl.pdfdemo.day05.p5;
/**
* @Author wfj
* @Date 2021/4/16
* @Description 接口面试题
* @Version 1.0
*/
public class InterviewTest2 {
}
interface Closeable {
void play();
}
interface Playable {
void play();
}
interface Rollable extends Closeable,Playable{
Ball ball = new Ball("lan");
}
class Ball implements Rollable{
private String name;
public String getName() {
return name;
}
public Ball(String name) {
this.name = name;
}
@Override
public void play() {
//编译报错,ball是一个常量,不可以再new
//ball = new Ball("tian");
System.out.println(ball.getName());
}
}
7)练习6
package com.yl.pdfdemo.day05.p5;
/**
* @Author wfj
* @Date 2021/4/16
* @Description
* @Version 1.0
*/
public class Circle {
private double radius;
public Circle() {
}
public Circle(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
}
package com.yl.pdfdemo.day05.p5;
/**
* @Author wfj
* @Date 2021/4/16
* @Description
* @Version 1.0
*/
public class ComparableCircle extends Circle implements CompareObject {
public ComparableCircle(double radius) {
super(radius);
}
@Override
public int compareTo(Object o) {
if (this == o) {
return 0;
}
if (o instanceof ComparableCircle) {
ComparableCircle c = (ComparableCircle) o;
if (this.getRadius() > c.getRadius()) {
return 1;
} else if (this.getRadius() < c.getRadius()) {
return -1;
} else {
return 0;
}
} else {
return 0;
}
}
}
package com.yl.pdfdemo.day05.p5;
/**
* @Author wfj
* @Date 2021/4/16
* @Description
* @Version 1.0
*/
public class ComparableCircleTest {
public static void main(String[] args) {
ComparableCircle c1 = new ComparableCircle(2.3);
ComparableCircle c2 = new ComparableCircle(2.3);
int i = c1.compareTo(c2);
if (i > 0) {
System.out.println("c1比c2大");
} else if (i < 0){
System.out.println("c1比c2小");
} else {
System.out.println("c1等于c2");
}
}
}
8)jdk8,接口新特性
package com.yl.pdfdemo.day05.p5;
/**
* @Author wfj
* @Date 2021/4/16
* @Description jdk8:除了定义全局常量和抽象方法之外,还可以定义静态方法,默认方法
* @Version 1.0
*/
public interface CompareA {
//静态方法
public static void method1() {
System.out.println("CompareA:CAT");
}
//默认方法
public default void method2() {
System.out.println("CompareB:DOG");
}
default void method3() {
System.out.println("CompareC:ROOT");
}
}
12.内部类
1)基本使用
package com.yl.pdfdemo.day05.p5;
/**
* @Author wfj
* @Date 2021/4/16
* @Description 内部类
* @Version 1.0
*/
public class InnerTest {
public static void main(String[] args) {
/**
* 内部类
* 1.java中,允许将一个类A声明在另一个类B中,则A类是内部类,B类是外部类
* 2.分类:
* 成员内部类(静态和非静态) vs 局部内部类(方法内,代码块内,构造期内)
*
* 3.成员内部类:
* 一方面:作为类的成员
* > 调用外部类的结构
* > 可以被static修饰
* > 可以被四种权限修饰符修饰
*
* 另一方面:作为一个类
* > 类内可以定义属性,方法,构造器等
* > 可以被final修饰,表示此类不可以被继承
* > 可以被abstract修饰
* 4.关注如下三个问题
* 4.1如何实例化成员内部类的对象
* 4.2如何在成员内部类中,区分调用外部类的结构
* 4.3开发中局部内部类的使用
*/
//创建Dog实例(静态的成员内部类)
Person.Dog dog = new Person.Dog();
dog.show();
//创建Bird实例(非静态成员内部类)
Person p = new Person();
Person.Bird bird = p.new Bird();
bird.sing();
bird.display("小兰");
}
}
class Person{
String name = "小明";
int age;
public void eat() {
System.out.println("Person eat...");
}
//静态成员内部类
static class Dog{
String name;
int age;
public Dog() {
}
public void show() {
}
}
//成员内部类
class Bird{
String name = "小白";
public Bird() {
}
public void sing() {
// 调用外部类非静态的方法,可以省略Person.this
Person.this.eat();
System.out.println("bird sing...");
}
public void display(String name) {
System.out.println(name);//方法形参
System.out.println(this.name);//内部类的属性
System.out.println(Person.this.name);//外部类的属性
}
}
public void method() {
//局部内部类
class AA{
}
}
static {
//局部内部类
class BB{
}
}
public Person(){
//局部内部类
class CC{
}
}
}
2)局部内部类的应用
package com.yl.pdfdemo.day05.p5;
/**
* @Author wfj
* @Date 2021/4/16
* @Description 局部内部类的应用
* @Version 1.0
*/
public class InnerTest1 {
// 开发中很少见
public void method() {
class ZZ{
}
}
//返回了一个实现Comparable接口的对象
public Comparable getComparable(){
//方式一,局部内部类
// class MyComparable implements Comparable{
@Override
public int compareTo(Object o) {
return 0;
}
}
return new MyComparable();
//方式二
return new Comparable() {
@Override
public int compareTo(Object o) {
return 0;
}
};
}
}
3)内部类面试题
package com.yl.pdfdemo.day05.p5;
/**
* @Author wfj
* @Date 2021/4/19
* @Description 内部类面试题
* @Version 1.0
*/
public class InnerTest2 {
/**
* 在局部内部类的方法中,如果调用局部内部类所声明的方法中的局部变量
* 要求此局部变量声明为final,因为method方法属于InnerTest2类的一部分,GG类只能取值,而不能改值
*
* jdk7之前,要求局部变量需要加上final修饰
* jdk8,默认可以省略final
*/
public static void main(String[] args) {
}
public void method(){
int num = 10;
class GG{
//不能修改常量的值
//num = 100;
public void show(){
System.out.println(num);
}
}
}
}