1. 黑马信息管理系统改进
1.1 黑马信息管理系统集合改进
使用数组容器的弊端
容器长度是固定的,不能根据添加功能自动增长 没有提供用于赠删改查的方法 优化步骤
创建新的StudentDao类,OtherStudentDao 创建ArrayList集合容器对象 OtherStudentDao中的方法声明,需要跟StudentDao保持一致
注意:如果不一致,StudentService中的代码就需要进行修改 完善方法(添加、删除、修改、查看) 替换StudentService中的Dao对象
1.1.1 修改OtherStudentDao类
import com. itheima. edu. info. manager. domain. Student ;
import java. util. ArrayList ;
public class OtherStudentDao extends BaseStudentDao {
private static ArrayList < Student > stus = new ArrayList < > ( ) ;
static {
Student stu1 = new Student ( "heima001" , "张三" , "23" , "1999-11-11" ) ;
Student stu2 = new Student ( "heima001" , "李四" , "24" , "2000-11-11" ) ;
stus. add ( stu1) ;
stus. add ( stu2) ;
}
@Override
public boolean addStudent ( Student stu) {
stus. add ( stu) ;
return true ;
}
@Override
public Student [ ] findAllStudent ( ) {
Student [ ] students = new Student [ stus. size ( ) ] ;
for ( int i = 0 ; i < students. length; i++ ) {
students[ i] = stus. get ( i) ;
}
return students;
}
@Override
public void deleteStudentById ( String delId) {
int index = getIndex ( delId) ;
stus. remove ( index) ;
}
@Override
public int getIndex ( String id) {
int index = - 1 ;
for ( int i = 0 ; i < stus. size ( ) ; i++ ) {
Student stu = stus. get ( i) ;
if ( stu != null && stu. getId ( ) . equals ( id) ) {
index = i;
break ;
}
}
return index;
}
@Override
public void updateStudent ( String updateId, Student newStu) {
int index = getIndex ( updateId) ;
stus. set ( index, newStu) ;
}
}
1.1.2 修改StudentService类
import com. itheima. edu. info. manager. dao. OtherStudentDao ;
import com. itheima. edu. info. manager. domain. Student ;
public class StudentService {
private OtherStudentDao studentDao = new OtherStudentDao ( ) ;
public boolean addStudent ( Student stu) {
return studentDao. addStudent ( stu) ;
}
public boolean isExists ( String id) {
Student [ ] stus = studentDao. findAllStudent ( ) ;
boolean exists = false ;
for ( int i = 0 ; i < stus. length; i++ ) {
Student student = stus[ i] ;
if ( student != null && student. getId ( ) . equals ( id) ) {
exists = true ;
break ;
}
}
return exists;
}
public Student [ ] findAllStudent ( ) {
Student [ ] allStudent = studentDao. findAllStudent ( ) ;
boolean flag = false ;
for ( int i = 0 ; i < allStudent. length; i++ ) {
Student stu = allStudent[ i] ;
if ( stu != null ) {
flag = true ;
break ;
}
}
if ( flag) {
return allStudent;
} else {
return null ;
}
}
public void deleteStudentById ( String delId) {
studentDao. deleteStudentById ( delId) ;
}
public void updateStudent ( String updateId, Student newStu) {
studentDao. updateStudent ( updateId, newStu) ;
}
}
1.2黑马信息管理系统抽取Dao
优化步骤
将方法向上抽取,抽取出一个父类 ( BaseStudentDao ) 方法的功能实现在父类中无法给出具体明确,定义为抽象方法 让两个类分别继承 BaseStudentDao ,重写内部抽象方法
1.2.1 修改BaseStudentDao类
import com. itheima. edu. info. manager. domain. Student ;
public abstract class BaseStudentDao {
public abstract boolean addStudent ( Student stu) ;
public abstract Student [ ] findAllStudent ( ) ;
public abstract void deleteStudentById ( String delId) ;
public abstract int getIndex ( String id) ;
public abstract void updateStudent ( String updateId, Student newStu) ;
}
1.2.2 修改StudentDao类
import com. itheima. edu. info. manager. domain. Student ;
public class StudentDao extends BaseStudentDao {
private static Student [ ] stus = new Student [ 5 ] ;
static {
Student stu1 = new Student ( "heima001" , "张三" , "23" , "1999-11-11" ) ;
Student stu2 = new Student ( "heima001" , "李四" , "24" , "2000-11-11" ) ;
stus[ 0 ] = stu1;
stus[ 1 ] = stu2;
}
@Override
public boolean addStudent ( Student stu) {
int index = - 1 ;
for ( int i = 0 ; i < stus. length; i++ ) {
Student student = stus[ i] ;
if ( student == null ) {
index = i;
break ;
}
}
if ( index == - 1 ) {
return false ;
} else {
stus[ index] = stu;
return true ;
}
}
@Override
public Student [ ] findAllStudent ( ) {
return stus;
}
@Override
public void deleteStudentById ( String delId) {
int index = getIndex ( delId) ;
stus[ index] = null ;
}
@Override
public int getIndex ( String id) {
int index = - 1 ;
for ( int i = 0 ; i < stus. length; i++ ) {
Student stu = stus[ i] ;
if ( stu != null && stu. getId ( ) . equals ( id) ) {
index = i;
break ;
}
}
return index;
}
@Override
public void updateStudent ( String updateId, Student newStu) {
int index = getIndex ( updateId) ;
stus[ index] = newStu;
}
}
1.2.3 修改OtherStudentDao类
import com. itheima. edu. info. manager. domain. Student ;
import java. util. ArrayList ;
public class OtherStudentDao extends BaseStudentDao {
private static ArrayList < Student > stus = new ArrayList < > ( ) ;
static {
Student stu1 = new Student ( "heima001" , "张三" , "23" , "1999-11-11" ) ;
Student stu2 = new Student ( "heima001" , "李四" , "24" , "2000-11-11" ) ;
stus. add ( stu1) ;
stus. add ( stu2) ;
}
@Override
public boolean addStudent ( Student stu) {
stus. add ( stu) ;
return true ;
}
@Override
public Student [ ] findAllStudent ( ) {
Student [ ] students = new Student [ stus. size ( ) ] ;
for ( int i = 0 ; i < students. length; i++ ) {
students[ i] = stus. get ( i) ;
}
return students;
}
@Override
public void deleteStudentById ( String delId) {
int index = getIndex ( delId) ;
stus. remove ( index) ;
}
@Override
public int getIndex ( String id) {
int index = - 1 ;
for ( int i = 0 ; i < stus. size ( ) ; i++ ) {
Student stu = stus. get ( i) ;
if ( stu != null && stu. getId ( ) . equals ( id) ) {
index = i;
break ;
}
}
return index;
}
@Override
public void updateStudent ( String updateId, Student newStu) {
int index = getIndex ( updateId) ;
stus. set ( index, newStu) ;
}
}
2 接口
2.1 接口的概述
接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。 当一个类中的所有方法都是抽象方法的时候,我们就可以将其定义为接口,接口也是一种引用数据类型,它比抽象类还要抽象 java中接口存在的两个意义
2.2 接口的定义和特点
接口用关键字interface来定义
接口不能实例化 接口和类之间是实现关系,通过implements关键字表示
public class 类名 implements 接口名 {} 接口的子类(实现类)
注意:接口和类的实现关系,可以单实现,也可以多实现。
public class 类名 implements 接口名1 , 接口名2 {} Inter接口
public interface Inter {
public abstract void study ( ) ;
}
public interface InterA {
public abstract void print1 ( ) ;
public abstract void print2 ( ) ;
public abstract void study ( ) ;
}
public class InterImpl implements Inter , InterA {
@Override
public void study ( ) {
System . out. println ( "我是实现类中的study方法" ) ;
}
@Override
public void print1 ( ) {
}
@Override
public void print2 ( ) {
}
}
public class Test1Interface {
public static void main ( String [ ] args) {
InterImpl ii = new InterImpl ( ) ;
ii. study ( ) ;
}
}
2.3 接口中成员的特点
成员变量
只能是常量 默认修饰符:public static final 构造方法
成员方法
只能是抽象方法 默认修饰符:public abstract 关于接口中的方法,JDK8和JDK9中有一些新特性
public interface Inter {
public static final int NUM = 10 ;
public abstract void show ( ) ;
}
public class TestInterface {
public static void main ( String [ ] args) {
System . out. println ( Inter . NUM) ;
}
}
class InterImpl extends Object implements Inter {
public InterImpl ( ) {
super ( ) ;
}
public void method ( ) {
System . out. println ( NUM) ;
}
public void show ( ) {
}
}
2.4 JDK8版中接口成员的特点——默认方法
JDK8版本后
允许在接口中定义非抽象方法,但是需要使用关键字 default 修饰,这些方法就是默认方法
接口中允许定义static静态方法 接口中默认方法的定义格式:
格式:public default 返回值类型 方法名(参数列表) { } 范例:public default void show() { } 接口中默认方法的注意事项:
默认方法不是抽象方法,所以不强制被重写。但是可以被重写,重写的时候去掉default关键字 public可以省略,default不能省略 如果实现了多个接口,多个接口中存在相同的方法声明,子类就必须对该方法进行重写
public interface InterA {
public default void show ( ) {
System . out. println ( "我是A接口中的show方法" ) ;
}
}
public interface InterB {
public default void show ( ) {
System . out. println ( "B....show方法" ) ;
}
}
public class TestInterface {
public static void main ( String [ ] args) {
InterAImpl ia = new InterAImpl ( ) ;
ia. show ( ) ;
}
}
class InterAImpl implements InterA , InterB {
@Override
public void show ( ) {
}
}
2.5 JDK8版中接口成员的特点——静态方法
JDK8版本后
接口中静态方法的定义格式:
格式:public static 返回值类型 方法名(参数列表) { } 范例:public static void show() { } 接口中静态方法的注意事项:
静态方法只能通过接口名调用,不能通过实现类名或者对象名调用 public可以省略,static不能省略
public interface InterA {
public static void show ( ) {
System . out. println ( "InterA...show" ) ;
}
}
public interface InterB {
public static void show ( ) {
System . out. println ( "InterB...show" ) ;
}
}
public class TestInterface {
public static void main ( String [ ] args) {
InterAImpl ia = new InterAImpl ( ) ;
InterA . show ( ) ;
InterB . show ( ) ;
}
}
class InterAImpl implements InterA , InterB {
}
2.6 JDK9版中接口成员的特点——私有方法
接口中私有方法的定义格式:
格式1:private 返回值类型 方法名(参数列表) { }
范例1:private void show() { } 格式2:private static 返回值类型 方法名(参数列表) { }
范例2:private static void method() { } 接口中私有方法的注意事项
默认方法可以调用私有的静态方法和非静态方法 静态方法只能调用私有的静态方法
public interface Inter {
public default void start ( ) {
System . out. println ( "start方法执行了..." ) ;
log ( ) ;
}
public default void end ( ) {
System . out. println ( "end方法执行了..." ) ;
log ( ) ;
}
private void log ( ) {
System . out. println ( "日志记录 ( 模拟 )" ) ;
}
private static void check ( ) {
System . out. println ( "权限校验 ( 模拟 )" ) ;
}
public static void open ( ) {
check ( ) ;
System . out. println ( "open方法执行了" ) ;
}
public static void close ( ) {
check ( ) ;
System . out. println ( "close方法执行了" ) ;
}
}
public class TestInterface {
public static void main ( String [ ] args) {
InterImpl ii = new InterImpl ( ) ;
ii. start ( ) ;
ii. end ( ) ;
Inter . open ( ) ;
Inter . close ( ) ;
}
}
class InterImpl implements Inter {
}
2.7 总结:接口的使用思路
如果发现一个类中所有的方法都是抽象方法,那么就可以将该类,改进为一个接口 涉及到了接口大面积更新方法,而不想去修改每一个实现类,就可以将更新的方法,定义为带有方法体的默认方法 希望默认方法调用的更加简洁,可以考虑设计为static静态方法。(需要去掉default关键字) 默认方法中出现了重复的代码,可以考虑抽取出一个私有方法。(需要去掉default关键字)
2.8 类和接口的关系
类和类的关系
类和接口的关系
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
public class Fu {
public void show ( ) {
System . out. println ( "Fu...show" ) ;
}
}
public interface Inter {
public default void show ( ) {
System . out. println ( "Inter....show" ) ;
}
}
public class TestInterface {
public static void main ( String [ ] args) {
InterImpl ii = new InterImpl ( ) ;
ii. show ( ) ;
}
}
class InterImpl extends Fu implements Inter {
}
public interface InterA {
public abstract void showA ( ) ;
public default void method ( ) {
System . out. println ( "InterA...method方法" ) ;
}
}
public interface InterB {
public abstract void showB ( ) ;
public default void method ( ) {
System . out. println ( "InterB...method方法" ) ;
}
}
public interface InterC extends InterA , InterB {
@Override
public default void method ( ) {
System . out. println ( "InterC接口,解决代码逻辑冲突问题, 重写method方法" ) ;
}
}
public class InterImpl implements InterC {
@Override
public void showA ( ) {
}
@Override
public void showB ( ) {
}
}
public class TestInterface {
public static void main ( String [ ] args) {
InterImpl ii = new InterImpl ( ) ;
ii. method ( ) ;
}
}
3 黑马信息管理系统使用接口改进
实现步骤:
将 BaseStudentDao抽象类改进为一个接口 让 StudentDao 和 OtherStudentDao 去实现这个接口
3.1 修改BaseStudentDao接口
import com. itheima. edu. info. manager. domain. Student ;
public interface BaseStudentDao {
public abstract boolean addStudent ( Student stu) ;
public abstract Student [ ] findAllStudent ( ) ;
public abstract void deleteStudentById ( String delId) ;
public abstract int getIndex ( String id) ;
public abstract void updateStudent ( String updateId, Student newStu) ;
}
3.2 修改StudentDao类
public class StudentDao implements BaseStudentDao {
}
3.3 修改OtherStudentDao类
public class OtherStudentDao implements BaseStudentDao {
}
4 多态
4.1 多态概述
什么是多态
同一个对象,在不同时刻表现出来的不同形态
举例:猫
我们可以说猫是猫:猫 cat = new 猫(); 我们也可以说猫是动物:动物 animal = new 猫(); 这里猫在不同的时刻表现出来了不同的形态,这就是多态 多态的前提和体现
public class Test1Polymorphic {
public static void main ( String [ ] args) {
Cat c = new Cat ( ) ;
Animal a = new Cat ( ) ;
a. eat ( ) ;
}
}
class Animal {
public void eat ( ) {
System . out. println ( "动物吃饭" ) ;
}
}
class Cat extends Animal {
@Override
public void eat ( ) {
System . out. println ( "猫吃鱼" ) ;
}
}
4.2 多态中的成员访问特点
构造方法:
同继承一样,子类会通过 super 访问父类构造方法 成员变量:
成员方法:
为什么成员变量和成员方法的访问不一样呢?
public class Test2Polymorpic {
public static void main ( String [ ] args) {
Fu f = new Zi ( ) ;
System . out. println ( f. num) ;
f. method ( ) ;
}
}
class Fu {
int num = 10 ;
public void method ( ) {
System . out. println ( "Fu.. method" ) ;
}
}
class Zi extends Fu {
int num = 20 ;
public void method ( ) {
System . out. println ( "Zi.. method" ) ;
}
}
4.3 多态的好处和弊端
多态的好处:
提高了程序的扩展性
具体体现:定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的任意子类对象 多态的弊端:
public class Test3Polymorpic {
public static void main ( String [ ] args) {
useAnimal ( new Dog ( ) ) ;
useAnimal ( new Cat ( ) ) ;
}
public static void useAnimal ( Animal a) {
a. eat ( ) ;
}
}
abstract class Animal {
public abstract void eat ( ) ;
}
class Dog extends Animal {
public void eat ( ) {
System . out. println ( "狗吃肉" ) ;
}
public void watchHome ( ) {
System . out. println ( "看家" ) ;
}
}
class Cat extends Animal {
public void eat ( ) {
System . out. println ( "猫吃鱼" ) ;
}
}
4.4 多态中的转型
public class Test4Polymorpic {
public static void main ( String [ ] args) {
Fu f = new Zi ( ) ;
f. show ( ) ;
Zi z = ( Zi ) f;
z. method ( ) ;
}
}
class Fu {
public void show ( ) {
System . out. println ( "Fu..show..." ) ;
}
}
class Zi extends Fu {
@Override
public void show ( ) {
System . out. println ( "Zi..show..." ) ;
}
public void method ( ) {
System . out. println ( "我是子类特有的方法, method" ) ;
}
}
4.5 多态中转型存在的风险和解决方案
风险
如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,那么在转换的时候就会出现ClassCastException 解决方案
关键字
使用格式
变量名 instanceof 类型 通俗的理解:判断关键字左边的变量,是否是右边的类型,返回boolean类型结果
public class Test3Polymorpic {
public static void main ( String [ ] args) {
useAnimal ( new Dog ( ) ) ;
useAnimal ( new Cat ( ) ) ;
}
public static void useAnimal ( Animal a) {
a. eat ( ) ;
if ( a instanceof Dog ) {
Dog dog = ( Dog ) a;
dog. watchHome ( ) ;
}
}
}
abstract class Animal {
public abstract void eat ( ) ;
}
class Dog extends Animal {
public void eat ( ) {
System . out. println ( "狗吃肉" ) ;
}
public void watchHome ( ) {
System . out. println ( "看家" ) ;
}
}
class Cat extends Animal {
public void eat ( ) {
System . out. println ( "猫吃鱼" ) ;
}
}
5 黑马信息管理系统使用多态改进
实现步骤
StudentDaoFactory类中方法的返回值定义成父类类型BaseStudentDao StudentService中接收方法返回值的类型定义成父类类型BaseStudentDao
5.1 修改StudentDaoFactory类
import com. itheima. edu. info. manager. dao. BaseStudentDao ;
import com. itheima. edu. info. manager. dao. OtherStudentDao ;
public class StudentDaoFactory {
public static BaseStudentDao getStudentDao ( ) {
return new OtherStudentDao ( ) ;
}
}
5.2 修改StudentService类
public class StudentService {
private BaseStudentDao studentDao = StudentDaoFactory . getStudentDao ( ) ;
}