1. 抽象类
当父类的一些方法不能确定时,可以用abstract关键字来修饰该方法,这个方法就是抽象方法,用abstract 来修饰该类就是抽象类。
抽象类的介绍
1) 用abstract 关键字来修饰一个类时,这个类就叫抽象类
访问修饰符 abstract 类名{
}
2)
用abstract 关键字来修饰一个方法时,这个方法就是抽象方法
访问修饰符 abstract 返回类型 方法名(参数列表);
3) 抽象类的价值更多是在于设计,是设计者设计好后,让子类继承并实现抽象类(即:实现抽象类的抽象方法)
4) 抽象方法在编程中用的不是很多,但是在公司笔试时,却是考官比较爱问的知识点
抽象类使用的注意事项和细节讨论
1) 抽象类不能被实例化 [举例]
2) 抽象类不一定要包含abstract方法。也就是说,抽象类可以没有abstract方法 [举例]
3) 一旦类包含了abstract方法,则这个类必须声明为abstract [说明]
4) abstract 只能修饰类和方法,不能修饰属性和其它的。[说明]
5) 抽象类可以有任意成员【因为抽象类还是类】,比如:非抽象方法、构造器、静态属性等等 [举例]
6) 抽象方法不能有主体,即不能实现.如图所示
7) 如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为abstract类。[举例 A类,B类,C类]
8) 抽象方法不能使用private、final 和 static来修饰,因为这些关键字都是和重写相违背的。说明: static关键字是不和重写相关,static方法不能重写
- 和前面一样,多态在抽象类上也体现在
多态数组【存放不同的子类对象, Dog和Cat】
多态参数【接收不同的子类对象】
1 public class AbstractPolyDemo { 2 3 public static void main(String[] args) { 4 // TODO Auto-generated method stub 5 6 Animal03 animals[] = new Animal03[2]; 7 animals[0] = new Cat03(); 8 animals[1] = new Dog03(); 9 10 //抽象类体现出多态数组 11 for (int i = 0; i < animals.length; i++) { 12 animals[i].eat(); 13 show(animals[i]); 14 } 15 16 } 17 18 //多态参数 19 public static void show(Animal03 animal) { 20 if (animal instanceof Cat03) { 21 Cat03 cat = (Cat03)animal; 22 cat.catchMouse(); 23 } else if (animal instanceof Dog03) { 24 Dog03 dog = (Dog03)animal; 25 dog.watchDoor(); 26 } 27 } 28 29 } 30 31 abstract class Animal03 { 32 33 abstract public void eat(); 34 } 35 36 class Cat03 extends Animal03 { 37 38 @Override 39 public void eat() { 40 // TODO Auto-generated method stub 41 System.out.println("小猫喜欢吃<・)))><<"); 42 } 43 44 public void catchMouse() { 45 System.out.println("小猫抓老鼠"); 46 } 47 48 } 49 50 class Dog03 extends Animal03 { 51 52 @Override 53 public void eat() { 54 // TODO Auto-generated method stub 55 System.out.println("小狗喜欢吃骨头~~"); 56 } 57 58 public void watchDoor() { 59 System.out.println("小狗看门~~"); 60 } 61
抽象类最佳实践-模板设计模式
1.1.1 基本介绍
抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为方式。
当功能内部一部分实现是确定,一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现。
编写一个抽象父类,父类提供了多个子类的通用方法,并把一个或多个方法留给其子类实现,就是一种模板模式。
最佳实践
设计一个抽象类(Template),能完成如下功能:
1) 编写方法caleTime() ,可以计算某段代码的耗时时间
2) 编写抽象方法code()
3) 编写一个子类Sub,继承抽象类Template,并实现code方法。
4) 编写一个测试类TestTemplate,看看是否好用。
1 public class AbstractTemplateDemo { 2 3 public static void main(String[] args) { 4 // TODO Auto-generated method stub 5 Sub sub = new Sub(); 6 sub.caleTime(); 7 8 Sub2 sub2 = new Sub2(); 9 sub2.caleTime(); 10 11 } 12 13 } 14 15 // 通过抽象类开发要给 模板设计模式 16 17 abstract class Template { 18 19 abstract public void code(); // code不确定. 20 // 统计code() 方法执行时间 21 22 public void caleTime() { 23 // 1先得到当前的时间(毫秒) 24 long nowTime = System.currentTimeMillis(); 25 code(); 26 // 2得到执行后的时间 27 long endTime = System.currentTimeMillis(); 28 System.out.println("执行代码时间为=" + (endTime - nowTime)); 29 } 30 } 31 32 class Sub extends Template { // 张三 33 34 @Override 35 public void code() { 36 // TODO Auto-generated method stub 37 // 测试 hello, 拼接 10000次 38 String str = "hello"; 39 for (int i = 0; i < 20000; i++) { 40 str += "jack" + i; 41 } 42 43 } 44 45 } 46 47 class Sub2 extends Template {// 李四 48 49 @Override 50 public void code() { 51 // TODO Auto-generated method stub 52 // 测试 hello, 拼接 10000次 53 StringBuilder str = new StringBuilder("hello"); 54 for (int i = 0; i < 20000; i++) { 55 str.append("jack" + i); 56 } 57 58 } 59 60 }
标准 服务 产品 项目
2.接口
接口快速入门
1 public class InterfaceDemo { 2 3 public static void main(String[] args) { 4 // TODO Auto-generated method stub 5 Computer computer = new Computer(); 6 Phone phone = new Phone(); 7 Camera camera = new Camera(); 8 9 computer.work(phone); //这里因为Phone已经实现了UsbInterface 10 computer.work(camera);//这里因为Camera已经实现了UsbInterface 11 12 } 13 14 } 15 16 17 class Computer { 18 public void work(UsbInterface usbInterace) { 19 //... 20 usbInterace.start(); 21 usbInterace.start(); 22 } 23 } 24 25 //定义给接口,要求各个类去实现 26 interface UsbInterface { 27 //定一些规范, 规范可以简单的理解就是方法(没有实现的方法) 28 public void start(); 29 public void stop(); 30 } 31 32 class Camera implements UsbInterface { 33 34 @Override 35 public void start() { 36 // TODO Auto-generated method stub 37 System.out.println("相机开始工作~~"); 38 } 39 40 @Override 41 public void stop() { 42 // TODO Auto-generated method stub 43 System.out.println("相机结束工作~~"); 44 45 } 46 47 } 48 49 class Phone implements UsbInterface { 50 51 @Override 52 public void start() { 53 // TODO Auto-generated method stub 54 System.out.println("手机开始工作~~"); 55 56 }
接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,在根据具体情况把这些方法写出来。
- 语法:
interface 接口名{
//属性
//抽象方法
}
class 类名 implements 接口{
自己属性;
自己方法;
实现的接口的抽象方法
}
- 小结:接口是更加抽象的抽象的类,抽象类里的方法可以有方法体,接口里的所有方法都
没有方法体【jdk7.0以前】。接口体现了程序设计的多态和高内聚低偶合的设计思想。高内聚坏了不会影响到别人,低耦合两个模块耦合性很低
- 特别说明:Jdk1.8后接口类可以有静态方法,默认方法,也就是说接口中可以有方法的
具体实现, 这个放在jdk8新特性说明
接口应用场景
1 public class InterfaceJdbcTest { 2 3 public static void main(String[] args) { 4 // TODO Auto-generated method stub 5 JdbcInterface jdbc = new MySqlDB(); 6 jdbc.connect(); 7 System.out.println(jdbc.operate()); 8 jdbc.close(); 9 10 jdbc = new DB2(); 11 12 jdbc.connect(); 13 System.out.println(jdbc.operate()); 14 jdbc.close(); 15 16 } 17 18 } 19 20 21 interface JdbcInterface { 22 public void connect(); 23 public String operate(); 24 public void close(); 25 } 26 27 class MySqlDB implements JdbcInterface { 28 29 @Override 30 public void connect() { 31 // TODO Auto-generated method stub 32 System.out.println("连接mysql"); 33 } 34 35 @Override 36 public String operate() { 37 // TODO Auto-generated method stub 38 return "操作mysql"; 39 } 40 41 @Override 42 public void close() { 43 // TODO Auto-generated method stub 44 System.out.println("关闭mysql"); 45 } 46 47 } 48 49 class DB2 implements JdbcInterface { 50 51 @Override 52 public void connect() { 53 // TODO Auto-generated method stub 54 System.out.println("连接DB2"); 55 56 } 57 58 @Override 59 public String operate() { 60 // TODO Auto-generated method stub 61 return "操作db2成功"; 62 } 63 64 @Override 65 public void close() { 66 // TODO Auto-generated method stub 67 System.out.println("关闭db2"); 68 } 69 70 }
注意事项和细节
1) 接口不能被实例化
2) 接口中所有的方法都public或者default 的抽象方法,图示:
3) 一个普通类实现接口,就必须将该接口的所有方法都实现。
4) 抽象类实现接口,可以不用实现接口的方法。
5) 一个类可以实现多个接口 [举例]
6) 接口中的属性,只能是常量,而且是 public static final 修饰符。比如:
int a=1; 实际上是 public static final int a=1; (必须初始化)
7) 接口中常量的访问形式: 接口名.变量名
8) 一个接口不能继承其它的类,但是可以继承多个别的接口 [举例]
9) 接口的修饰符 只能是 public 和默认,这点和类的修饰符是一样的。
1 public class ExtendsVSImplement { 2 3 public static void main(String[] args) { 4 // TODO Auto-generated method stub 5 6 LittleMonkey littleMonkey = new LittleMonkey("悟空", (short)10); 7 littleMonkey.climbing(); 8 littleMonkey.fly(); 9 littleMonkey.swim(); 10 11 Monkey m = littleMonkey; 12 m.climbing(); 13 IBirdable a = littleMonkey; 14 a.fly(); 15 IFishable b = littleMonkey; 16 b.swim(); 17 18 19 20 } 21 22 } 23 24 //猴子类 25 class Monkey { 26 private String name; 27 private short age; 28 29 30 31 public Monkey(String name, short age) { 32 super(); 33 this.name = name; 34 this.age = age; 35 } 36 37 public void climbing() { 38 System.out.println(name + " 能爬树~~"); 39 } 40 41 public String getName() { 42 return name; 43 } 44 45 public void setName(String name) { 46 this.name = name; 47 } 48 49 public short getAge() { 50 return age; 51 } 52 53 public void setAge(short age) { 54 this.age = age; 55 } 56 57 58 } 59 60 interface IBirdable { 61 public void fly(); 62 } 63 interface IFishable { 64 public void swim(); 65 } 66 67 class LittleMonkey extends Monkey implements IBirdable,IFishable { 68 69 70 public LittleMonkey(String name, short age) { 71 // TODO Auto-generated constructor stub 72 super(name, age); 73 } 74 75 public void fly() { 76 System.out.println(getName() + " 通过学习会飞翔~~"); 77 } 78 public void swim() { 79 System.out.println(getName() + " 通过学习会游泳~~"); 80 } 81 }
3.接口和继承比较
实现接口可以看作是对继承的一种补充
java的继承是单继承,也就是一个类最多只能有一个父类,这种单继承的机制可保证类的
纯洁性,比c++中的多继承机制简洁。但是不可否认,对子类功能的扩展有一定影响.所以
我们认为: 实现接口可以看作是对 继承的一种补充
- 接口和继承解决的问题不同
继承的价值主要在于:解决代码的复用性和可维护性。
接口的价值主要在于:设计,设计好各种规范(方法),让其它类去实现这些方法。
- 接口比继承更加灵活
接口比继承更加灵活,继承是满足 is - a的关系,而接口只需满足 like - a的关系。
- 接口在一定程度上实现代码解耦
接口练习:
4.内部类
1.1.1 基本介绍
一个类的内部又完整的嵌套了另一个完整的类结构。被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer class)。是我们类的第五大成员
类的五大成员是哪些?[属性,方法,构造器,代码块,内部类]】,内部类最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系。
1.1.1 基本语法
class Outer{ //外部类
class
Inner{ //内部类
}
}
class Other{ //外部其他类
}
1.1.1 内部类的分类
- 定义在外部类的成员位置上:
1) 成员内部类(没用static修饰)
2) 静态内部类(使用static修饰)
- 定义在外部类局部位置上(比如方法内):
1) 局部内部类(有类名)
2) 匿名内部类(没有类名)
1.1.2 成员内部类的使用
说明:成员内部类是定义在外部类的成员位置,并且没有static修饰。
1) 可以直接访问外部类的所有成员,包含私有的
2) 可以添加任意访问修饰符(public、protected 、默认、private),因为它的地位就是一个成员.
3) 作用域
和外部类的其他成员一样,为整个类体, 比如前面案例,在外部类的成员方法中创建成员内部类对象,再调用方法
4) 成员内部类---访问---->外部类(比如:属性) [访问方式:直接访问] (说明)
5) 成员外部类---访问------>内部类 (说明)
访问方式:创建对象,再访问
6) 外部其他类---访问---->成员内部类
7) 如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.this.成员)去访问
1.1.1 静态内部类的使用
1) 说明:静态内部类是定义在外部类的成员位置,并且有static修饰
2) 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
3) 可以添加任意访问修饰符(public、protected 、默认、private),因为它的地位就是一个成员。
4) 作用域
同其他的成员,为整个类体
5) 静态内部类---访问---->外部类(比如:静态属性) [访问方式:直接访问所有静态成员]
6) 外部类---访问------>静态内部类 访问方式:创建对象,再访问
7) 外部其他类---访问----->静态内部类
8) 如果外部类和静态内部类的成员重名时,静态内部类访问的时,默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.成员)去访问