抽象
概念
当我们做子类共有功能抽取时,随着抽取的次数的增加,我们父类个概念会越来与模糊化,无法具体体现时,这时候类需要设定为抽象的,举个例子来理解一下
未使用抽象
public class Pet {
private int id;
private String name;
private int health = 60;
private int love;
public Pet() {}
//Object是所有类的父类
public Pet(String name, int health, int love) {
super();
this.name = name;
this.health = health;
this.love = love;
}
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 getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public int getLove() {
return love;
}
public void setLove(int love) {
this.love = love;
}
public void eat(String food) {
}
public void print() {
System.out.print("宠物的自白:我的姓名为"+name+", 健康值为:"+health+", 与主人的亲密度为:"+love);
}
}
public class PetDemo {
public static void main(String[] args) {
//创建一个Pet的对象
Pet pet = new Pet();
//虽然宠物这个对象能创建,但是创建出来之后,却不知道宠物到底是啥
//所以我们应该使父类成为一个抽象类,阻止其直接实例化
pet.setName("未知");
pet.setHealth(60);
pet.setLove(20);
pet.eat("大骨头");
pet.print();
}
}
因为父类的概念抽象化,创建的对象无法识别具体描述,需要将父类设置未抽象类,阻止其创建对象
抽象关键字 abstract
抽象类: 使用abstract修饰的类叫做抽象类,抽象类只能被继承不能直接实例化
抽象方法: 使用abstract修饰的方法叫做抽象方法,抽象方法没有方法体,在子类中必须实现该方法,除非子类是一个抽象类
如果父系整个体系中所有的抽象方法,在最后的子类必须全部重写(实现)
//abstract一般用于修饰父类为抽象类
public abstract class Pet {
private int id;
private String name;
private int health = 60;
private int love;
public Pet() {}
//Object是所有类的父类或祖宗类
public Pet(String name, int health, int love) {
super();
this.name = name;
this.health = health;
this.love = love;
}
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 getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public int getLove() {
return love;
}
public void setLove(int love) {
this.love = love;
}
//使用abstract修饰的方法,叫做抽象方法,抽象方法没有方法体
//抽象方法,在子类中必须被实现,除非子类是抽象类
public abstract void eat(String food);
public void print() {
System.out.print("宠物的自白:我的姓名为"+name+", 健康值为:"+health+", 与主人的亲密度为:"+love);
}
}
//子类
public class Dog extends Pet{
@Override
public void eat(String food) {
System.out.println("子类中必须实现父类中的抽象方法");
}
}
//测试类
public class PetDemo {
public static void main(String[] args) {
//当父类设置为抽象类后,父类无法被实例化
//Pet pet = new Pet();
//虽然宠物这个对象能创建,但是创建出来之后,却不知道宠物到底是啥
//所以我们应该使父类成为一个抽象类,阻止其直接实例化,只能被继承
Pet pet = new Dog();
pet.eat("dasf");
}
}
抽象类与抽象方法的关系
在抽象类中可以没有抽象方法,有抽象方法的类,必须是抽象类
static静态关键字
static表示为静态,可以用于修饰方法和属性
static修饰的特点
static修饰的属性和方法属于类,直接通过类就可以使用,且被类的对象所共享,这也是我们判定是否为静态的关键.
static修饰属性
public class Dog {
//使用static修饰属性
public static String name;
private int age;
private String strain;
public static String getName() {
return name;
}
public static void setName(String name) {
Dog.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getStrain() {
return strain;
}
public void setStrain(String strain) {
this.strain = strain;
}
}
public class Demo {
public static void main(String[] args) {
// 类中静态的内容被类直接使用,不管何时何地使用name,都是同一个name
Dog.name = "旺财";
//创建一个Dog对象
Dog dog = new Dog();
dog.setAge(2);
dog.setStrain("可爱的茶杯犬");
System.out.println("我的名字叫:"+dog.name+", 年龄为:"+dog.getAge()+", 我是一只"+dog.getStrain());
dog.name = "旺旺";
System.out.println("现在的名称为:"+Dog.name);
}
}
静态访问特点
非静态成员方法可以访问静态成员和非静态成员
静态方法 只能访问静态成员
描述: 因为静态成员属于类,在类被加载,静态成员已经存在,这是对象还没有创建,非静态成员还没有实例化
非静态在创建对象后使用,那么这时候静态内容是存在的,可以使用
public class Dog {
//使用static修饰属性
public static String name;
private int age;
private String strain;
public static String getName() {
return name;
}
public static void setName(String name) {
Dog.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getStrain() {
return strain;
}
public void setStrain(String strain) {
this.strain = strain;
}
public static void print() {
//静态成员属于类,在类存在时就可以使用,非静态成员属于对象,只有在创建对象之后使用
// System.out.println("宠物的独白,我的名字叫"+name+", 年龄为:"+age);
System.out.println("这是一个静态方法");
}
public void show() {
//非静态成员方法可以使用静态成员
System.out.println("宠物的独白,我的名字叫"+name+", 年龄为:"+age+" ,品种为:"+strain);
print();
}
}
public class Demo {
public static void main(String[] args) {
// 类中静态的内容被类直接使用,不管何时何地使用name,都是同一个name
Dog.name = "旺财";
//创建一个Dog对象
Dog dog = new Dog();
dog.setAge(2);
dog.setStrain("可爱的茶杯犬");
System.out.println("我的名字叫:"+dog.name+", 年龄为:"+dog.getAge()+", 我是一只"+dog.getStrain());
dog.name = "旺旺";
System.out.println("现在的名称为:"+Dog.name);
//调用类中的静态方法
Dog.print();
dog.print();
}
}
代码加载顺序
1.优先加载静态内容,静态内容从上到下
2.加载非静态内容 ,构造方法,代码块,其他内容,从上到下
接口
1.什么是接口?
接口就是一种公共的规范标准,只要符合规范标准,大家都可以使用
理解: 接口只是提出功能,并不去实现功能,功能由子类实现类去进行重写
2.接口的作用
接口更多体现于对行为的抽象,主要解决了继承关系中的单继承问题,接口可以进行多实现.
3.接口的组成
也可以把接口看做时一个特殊的抽象类,接口中只有抽象方法和静态常量
但是在JDK1.8之后,为接口提供了默认方法(实体方法),使用default修饰
4.接口关键字
接口关键字 interface
实现接口的关键字 implements
//使用interface修饰的叫做接口
public interface USBInterface {
//接口中只有静态常量,static和final是默认提供的
public static final int WEEK=7;
//抽象方法,USB提供服务方法
public abstract void service();
}
//implements实现接口关键字
public class USan implements USBInterface {
//实现接口必须重写接口中所有的抽象方法
@Override
public void service() {
System.out.println("USB风扇连接成功,通电了风扇转起来了...");
}
}
public class UDisk implements USBInterface {
@Override
public void service() {
System.out.println("U盘接入到USB接口,可以开始交互数据.....");
}
}
public class UMouse implements USBInterface {
@Override
public void service() {
System.out.println("USB鼠标已接入,可以开始进行操作....");
}
}
public class Demo {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("1.风扇\t2.鼠标\t3.U盘");
System.out.println("请选择你要接入的产品:");
int choose = in.nextInt();
//父接口引用
USBInterface usb = null;
//通过不同选择指向不同子类对象
if(choose==1) {
usb = new USan();
}else if(choose==2)
usb = new UMouse();
else
usb = new UDisk();
//调用接口的统一应用
usb.service();//选择2:USB鼠标已接入,可以开始进行操作....
}
}
5.接口解决单继承问题
例题: 当我们需要组装一个门的时候,门包含两部分,1.门板 2.锁;单继承无法满足我们的需求
分析: 1.将门设置为父类 包含 开门() 关门()
2.将锁设置为接口 包含:开锁() 关锁()
//门抽象类
public abstract class Door {
public abstract void open();
public abstract void close();
}
//锁的接口
public interface Lock {
//在接口中只有抽象方法,所以abstract可以省略
public void openLock();
public void closeLock();
}
//解决单继承问题,在继承的同时可以实现接口,如果想要多实现,接口之间使用逗号隔开
public class NormalDoor extends Door implements Lock {
@Override
public void openLock() {
System.out.println("钥匙往右转三圈,锁打开了,取出钥匙");
}
@Override
public void closeLock() {
System.out.println("钥匙往左转三圈,锁上了,取出钥匙");
}
@Override
public void open() {
System.out.println("脚一踹,门就躺下了");
}
@Override
public void close() {
System.out.println("脚一勾,门又关上了");
}
}
//测试类
public class Demo {
public static void main(String[] args) {
NormalDoor nd = new NormalDoor();
nd.openLock();
nd.open();
nd.close();
nd.closeLock();
//这种情况如果采用接口引用,那么无法使用Door父类中的内容
Lock lock = new NormalDoor();
lock.openLock();
lock.closeLock();
}
}