课时1 面向对象简介
20180101
面向对象,模块化设计,具备可通用性,可重用
1. 封装性:内部的操作对外部不可见
2. 继承性:继续发展,可以重用设计
3. 多态性:利用这个特性得到良好的设计,可控范围内的状态改变
OOA面向对象分析
OOD面向对象设计
OOP面向对象编程
核心所在--考虑内存分配问题
面向过程,函数式过程,解决问题
20180102
课时2 类和对象(基本定义)
类:引用数据类型,内存分配问题
描述的群体共性特征(比如:人)
对象是一个具体的可以使用概念(比如具体的某个人)
类 ---> 对象
类的组成:方法(操作的行为),属性(变量,描述对象的基本特点)
课时3 类和对象(定义)
class ThisIsAClass {
属性1;
属性2;
方法1() {
方法内容
}
方法2() {
方法内容
}
}
属性可以无限定义,注意每一个方法中的代码不要太长,否则就要考虑重构;
声明并实例化对象
类名称 对象名称 = new 类名称();
分部进行
1. 声明:类名称 对象名称 = null;
2. 实例化: 对象名称 = new 类名称();
引用数据类型,new用于开辟新的堆内存;
性能调优:内存问题
对象只有实例化之后才能使用:
调用类中的属性 对象名称.属性;
调用类中的方法 对象名称.方法名();
课时4 类和对象(对象内存分析)
引用类型
堆内存:保存真正的数据,对象的属性信息
栈内存:保存的堆内存的地址,也就是堆内存的操作权
如果在定义类的时候没有给属性声明默认值,那么属性会采用类型的默认值,比如int是0,String是null
1个栈只能存储1个地址
声明并实例化对象方式:
分步方式:
如果只是声明对象,而不实例化,编译的时候不会报错,运行的时候会报错:NullPointerException
数组,类,接口会出现此类报错
课时5 类和对象(引用传递初次分析)
引用的本质是别名,别名存在栈内存中,1个堆内存可以被多个栈内存所指向(比如同一个人有多个外号,但是其实是指向同一个人)
内存分析(地址一样)
垃圾内存:(没有栈内存指向的堆内存空间,会被GC定期回收) GarbageCollection
课时6 private实现封装处理
面向对象编程有三大特性:封装、继承、多态
对象不能直接 . 操作类的属性
封装可以使用private实现(有其他实现方式,不唯一),只允许本类访问
方法一般不使用private
语法格式:
private 属性;
配置属性使用setter方法(可以对变量做合理判断),获取属性使用getter方法
publicclass Person {
private String name;
public void setName(String a) {
name = a;
}
public void getName() {
return name;
}
}
publicstatic void main (String[] args) {
Person per = new Person();
per.setName("test");
per.getName();'
}
规范:
类中的所有属性定义都是用private封装,如果需要被外部使用,就定义setter()和getter()方法
课时7 构造方法和匿名函数
实例化对象方式:
类名称 对象名称 =new 类名称();
类名称:任何对象都有其对应的类
对象名称:对象的唯一标记
new:开辟新的堆内存空间
类名称():构造方法
构造方法和类名称一样,无返回值,声明一个类之后就会自动生成一个无参数无返回值的默认构造函数(编译后)
new的时候才调用构造方法
类的组成,属性+普通方法+构造方法
publicclass Person {
private String name;
public Person() { //默认的构造方法格式
}
public void setName(String a) {
name = a;
}
public void getName() {
return name;
}
}
publicstatic void main (String[] args) {
Person per = new Person();
per.setName("test");
per.getName();'
}
构造方法不能带void修饰符,带有void的命令不标准,
publicvoid Person()
publicPerson()
对于内中可以自动生成默认构造方法,前提是类中没有定义同名的构造方法
构造方法可以把类中的属性初始化(传入参数的构造方法)
构造方法可以重载(不同参数类型,不同参数个数),注意定义结构,按照参数个数采用升序或者降序排列
定义类的步骤:
1. 写属性
2. 写构造方法
3. 写普通方法
匿名对象:
只有这样定义: newPerson();
没有栈空间,使用一次之后就成为垃圾内存
课时8 【第01个代码模型】综合案例:简单Java类
简单java类的开发要求
1. 类的名称有意义,可以明确的描述某一类事物
2. 类中所有的属性使用private封装,并提供setter()/getter()方法
3. 类中必须保留一个无参数的构造方法
4. 类中的所有方法不允许使用System.out方法,输出要在调用处完成
5. 类中应该提供一个返回类完整信息的方法,getInfo()
开发中最多是简单java类
开发原则
课时9 数组的定义和使用(基本概念)
一组相关类型的变量集合,可以按照统一的方式进行操作,是引用类型
数组动态初始化(声明之后,每个数据都为默认值,比如int为0)
1. 声明并开辟空间
数据类型[] 数组名称 =new 数据类型[长度]
或者
数据类型 数组名称[] =new 数据类型[长度]
2. 分部进行(先声明,再实例化)
数据类型[] 数组名称 =null
数组名称 =new 数据类型[长度]
操作方式:
数组的访问通过索引完成,索引从0开始,到数组长度-1
比如int[]data = new int[3],索引为0,1,2
- 数组初始化之后,每个数据都为默认值,比如int为0
- 是一个有序的集合操作,采用循环模式操作
- 数组长度data.length
课时10 数组的定义与使用(数组引用传递)
int[]data = new int[3];
int[]temp = null;
temp= data;
//temp和 data指向同一块堆内存
//data的栈内存存的是地址
课时11 数组的定义与使用(数组静态初始化)
数组定义的时候设定内容
语法:
1. 简化格式
数据类型数组名称[] ={value,value,...,value};
2. 建议使用,完整格式,可以使用匿名数组
数据类型 数组名称[]=new 数据类型[] {value,value,...,value};
intdata[] = new int[] {1,2,3,4,5,6};
缺陷:长度固定
课时12 数组的定义与使用(二维数组)
行列集合
数组[行索引][列索引]
语法模式和一维一样
intdata[][] = new int[][] { {1,2,3},{4,5},{6,7,8,9} };
遍历数组使用2重循环,外部行,内部列
for(int x=0; x < data.length; x++) {
for (int y=0; y < data[x].length; y++){
System.out.print(data[x][y]);
}
}
//开发过程中出现二维数组的概率不高
课时13 数组的定义与使用(数组与方法的操作)
方法接收数组(参数为数组)
publicstatic void printArray(int temp[]) {
//
}
方法返回数组
publicstatic int[] init() {
return new int[] {1,2,3,4,5};
}
传入数组,返回数组
publicstatic void inc(int arr[]) {
for (int x = 0; x < arr.length; x++) {
arr[x] *= 2;
}
}
课时14 数组的定义与使用(Java对数组的支持)
1. 数组排序(基本数据类型数组),升序
java.util.Arrays.sort(数组名称);
2. 数组拷贝(一个数组的部分内容替换另外一个数组的部分内容),连续替换
System.arraycopy(原数组名称,原数组起点,目标数组名称,目标数组起点);
//逻辑训练,开发用不上
课时15 数组的定义与使用(数组案例:数组数据统计)
数组的线性操作
最大,最小,平均,总和
循环操作模式完成
方法优化
课时16 数组的定义与使用(数组案例:数组排序)
1. 基础排序操作:
冒泡排序:
publicclass ArrayDemo {
public static void main(String[] args){
int score[] = {67, 69, 75, 87, 89, 90,99, 100};
for (int i = 0; i < score.length-1; i++){ //最多做n-1趟排序
for(int j = 0 ;j < score.length- i - 1; j++){ //对当前无序区间score[0......length-i-1]进行排序(j的范围很关键,这个范围是在逐步缩小的)
if(score[j] < score[j +1]){ //把小的值交换到后面
int temp = score[j];
score[j] = score[j + 1];
score[j + 1] = temp;
}
}
System.out.print("第"+ (i + 1) + "次排序结果:");
for(int a = 0; a System.out.print(score[a] +"\t"); } System.out.println(""); } System.out.print("最终排序结果:"); for(int a = 0; a System.out.print(score[a] +"\t"); } } } 课时17 数组的定义与使用(数组转置) 首尾交换 1. 新定义一个空数组,然后把原数组的值从后到前存入新的数组 问题:开辟了两块相同的堆内存空间,造成浪费 2. 在原数组上反转 计算数组长度/2,交换次数为n,n =(array.length -1)/2 0 和length-1交换 1 和length-2交换 2 和length-3交换 n 和length-n-1交换 课时18 数组的定义与使用(二分查找法) 指定的数组中查找某个元素的位置 前提:数组先排序 mid =head/2 + tail/2 原理 比如一个排序好的数组 0,1,2,3,4,5,6,7,8 查找7 第一次查找 from:0 to:8 mid:4 索引为4的数比7小,所以赋值(第二次查找) from:4+1 to:8 mid:(5+8)/2= 6 索引为6的数比7小,所以赋值(第三次查找) from:6+1 to:8 mid:(7+8)/2= 7 索引为7的数为7,返回索引7 查找2 第一次查找 from:0 to:8 mid:4 索引为4的数比2大,所以赋值(第二次查找) from:0 to:4-1 mid:(0+3)/2= 1 索引为1的数比2小,所以赋值(第三次查找) from:1+1 to:3 mid:(2+3)/2= 2 索引为2的数为2,返回索引2 递归的结束条件是当from>= to 课时19 数组的定义与使用(对象数组) 核心掌握 引用数据类型为主,类或者接口 对象数组动态初始化: 类名称[] 对象数组名 =new 类名称[长度] 对象数组的静态初始化:类名称[] 对象数组名 =new 类名称[] {对象名,...} classPerson { private String name; private int age; public Person(String setName,int setAge){ name = setName; age = setAge; } public String getInfo() { return "name is " + name+ " age is " + age; } } publicclass ArrayDemo { public static void main(String[] args) { Person[] per = new Person[3]; //动态初始化,默认值为null per[0] = newPerson("A",1); per[1] = newPerson("B",2); per[2] = newPerson("C",3); for (int x = 0; x < per.length;x++) { System.out.println(per[x].getInfo()); } Person[] per2 = new Person[] { newPerson("D",4) }; //静态初始化 System.out.println(per2[0].getInfo()); } } 对象保存的是堆内存的地址 普通数据数组堆内存直接保存数据,比如newint[] 而对象数组堆内存表示各个对象的真是数据地址(里面没有数据),如上图 课时20 String类的基本特点(String类两种实例化方式) 所有开发过程中都存在String类 第一种 String str ="hello"; str是一个对象,hello是保存在堆内存中 第二种 Stringstr = new String("hello"); 传入"hello"的名为String的构造函数 课时21 String类的基本特点(字符串比较) == 和 equals的区别 ==比较的是堆内存的地址,是数值比较 equals()比较的是字符串内容,区分大小小 String str1 ="hello"; //把一个匿名对象值为"hello"的对象命名为str1 String str2 = newString("hello"); str1 == str2 结果为false str1.equals(str2) 结果为true 开发过程中必须使用equals() 课时22 String类的基本特点(字符串常量为匿名对象) String str1 ="hello"; //把一个匿名对象值为"hello"的对象命名为str1 开发过程中,如果要判断用户输入的字符串是否等同于指定的字符串,一定要把字符串写在前面,考虑用户没有输入数据的问题 操作方法1:字符串写在前面,不会报空指向异常 课时23 String类的基本特点(String两种实例化区别) 第一种 直接赋值(开发推荐做法,节省内存) String str ="hello"; str是一个对象,hello是保存在堆内存中 多次赋值(指向的是同一个堆内存),使用了共享设计模式 JVM维护对象池, 直接赋值的时候,第一次会保存到对象池,后续如果有一样的对象,就引用一样的对象 也就是一个对象数组,可以减少同样字符串的内存开销 第二种,构造方法(标准做法) (从右往左执行) Stringstr = new String("hello"); 传入"hello"的名为String的构造函数 会开辟2个堆内存空间,其中一个成为垃圾空间 而且这个对象没有自动保存到对象池 实现入池的操作 publicString intern(); 课时24 String类的基本特点(字符串常量不可变更) 字符串对象变更: 字符串内容本身是不会变化的,变化的是字符串对象的引用 开发原则: 字符串采用直接赋值模式完成 比较实用equals()方法实现 字符串不要频繁改变 课时25 String类的常用方法(DOC文档组成) 文档组成: 1. 类的相关定义,类的名字,父类,接口等 2. 类的简介 3. 成员(field)摘要,属性就是一种成员, 4. 构造(constructor)方法说明,Deprecated建议不用 5. 方法(methods)摘要,返回值,参数说明 课时26 String类的常用方法(字符串与字符数组) 字符数组 变成 字符串 public String(char[] value)//构造方法 public String(char[] value,int offset, int count) // offset开始,count个数,构造方法 public char charAt(int index)//返回字符串索引位置的字符,索引从0开始 开发中出现的几率很低,普通方法 字符串 变成 字符数组 publicchar[] toCharArray() //普通方法 重点:字符串和字符数组的互相转换 publicclass StringDemo { public static void main(String[] args) { String str = "helloworld"; System.out.println("index 2" + str.charAt(2)); char[] data = str.toCharArray(); for (char x : data) { x -= 32; //转换成大写 System.out.print(x +"/"); } System.out.println(newString(data)); System.out.println(newString(data,6,5)); } } 课时27 String类的常用方法(字节与字符串) 字节:数据传输或者编码转换 支持: 构造方法: public String(byte[] byte) public String(byte[] byte,int offset, int length) 普通方法: public byte[] getBytes() public byte[] getBytes(StringcharsetName) throws UnsupportedEncodingException //编码转换 public class StringDemo { public static void main(String[] args) { String str = "hello world"; byte data[] = str.getBytes(); for (byte x : data) { System.out.print(x + ","); } } } 字节 -128 到 127 无法表示中文 字符才用于表示中文 课时28 String类的常用方法(字符串比较) equals()方法 区分大小写 public boolean equals(StringanotherString) 不区分 public booleanequalsIgnoreCase(String anotherString) public int compareTo(StringanotherString) //比较两个字符串的大小关系 相等返回0 如果不相等: 小于(每个字符进行对比,根据编码数字差返回第一个不相等的字符差) 大于(每个字符进行对比,根据编码数字差返回第一个不相等的字符差) 这个方法很重要 public class StringDemo { public static void main(String[] args) { String str1 = "hello"; System.out.println("Hello".equals(str1)); System.out.println("Hello".equalsIgnoreCase(str1)); System.out.println("A".compareTo("a")); System.out.println("a".compareTo("A")); System.out.println("abb".compareTo("adc")); } } /* E:\01_JAVA\project\java_basic\mldn\02\course_28>javaStringDemo false true -32 32 -2 */ 课时29 String类的常用方法(字符串查找)- 重要 contains() // 普通方法,判断一个子字符串是否存在,返回booleanJDK1.5之后追加 indexOf() // 普通方法,查找子字符串的索引,返回第一个字符的位置索引,不存在则返回-1 indexOf(String str, intindex) //从指定位置开始查找 lastIndexOf() //从后向前找 lastIndexOf(String str, intindex) //从指定位置从后往前找 startsWith(String prefix) // 由指定子字符串开头 startsWith(String prefix, inttoffset) //从指定位置开始判断,由指定子字符串开头 endsWith(String prefix) //由指定子字符串结尾 建议使用contains() 课时30 String类的常用方法(字符串替换) 指定一个新的字符串替换字符串中的某个字符串 //需要替换的字符串 目标字符串 replaceAll(String regex,String replacement) replaceFirst(String regex,String replacement) 课时31 String类的常用方法(字符串拆分) string[] split(String regx) string[] split(String regx,int limit) // 部分拆分,分成几段,2 代表2段 最大长度,如果没有到最大长度,那就有多少拆多少 \\转义字符 课时32 String类的常用方法(字符串截取) substring(int beginindex) //从指定索引截取到结尾 substring)int beginindex, intendindex) //指定区间截取 索引从0开始 课时33 String类的常用方法(字符串其它操作方法) trim() //去掉字符串的左右空格,一个或者多个 toUpperCase() //转大写 toLowerCase() //转小写 这两个函数,如果不是字母,那么就不做转换 intern() //字符串存入对象池 contact(String str) //字符串连接,跟+一样 length() //字符串长度 isEmpty() //判断是否为空字符串,长度为0,非null 没有提供首字符大写的方法 实现首字母大写的方法 课时34 this关键字(this调用属性) this 可以调用 1. 本类属性 2. 本类方法(构造和普通) 3. 当前对象(相对概念) 下面赋值运行之后,name 为 null,age 为 0; 程序以大括号为边界,不会去找外部定义的属性name 参数与属性同名,解决方法 类的方法中有需要用到属性,一定在前面加this关键字 课时35 this关键字(this调用方法) this.函数名称(参数) this.构造方法名称(参数) 区分方法的定义来源(继承中有用) java支持类构造方法的互相调用: 例子,使用2个参数的调用,先调用1个参数的,再赋值age,调用1个参数的时候,使用无参数的构造函数先输出一段信息,然后再赋值name 有以下几点要求 this() 1. this()必须放在构造方法的首行 2. 使用this()构造方法的时候留出口(递归死循环)(比如在上面这个例子中无参构造里面调用2个参数的构造函数) 课时36 this关键字(表示当前对象) this指向p1 课时37 引用传递进阶分析 java核心 3个简单例子 第一个: class Message { private int num ; public void setNum(int num) { this.num = num ; } public int getNum() { return this.num ; } } public class TestDemo { public static void main(String[] args) { Message msg = new Message(); msg.setNum(100); fun(msg); System.out.println(msg.getNum()); } public static void fun(Message temp) { temp.setNum(30); } } 第二个: public class TestDemo2 { public static void main(String[] args) { String str = "hello"; fun(str); System.out.println(str); } public static void fun(String temp) { temp = "world"; } } 第三个: classMessage2 { private String note ; public void setNote(String note) { this.note = note ; } public String getNote() { return this.note ; } } publicclass TestDemo3 { public static void main(String[] args) { Message2 msg = new Message2(); msg.setNote("hello"); fun(msg); System.out.println(msg.getNote()); } public static void fun(Message2 temp) { temp.setNote("world"); } } 课时38 【第02个代码模型】综合案例:对象比较 比较两个对象的属性 实现形式1 classPerson { private String name ; private int age ; public Person(String name, int age) { this.name = name ; this.age = age ; } public String getName() { return this.name ; } public int getAge() { return this.age ; } } publicclass TestDemo1 { public static void main(String[] args) { Person perA = newPerson("A",20); Person perB = newPerson("A",20); System.out.println(perA == perB); if(perA.getAge() == perB.getAge()&& perA.getName().equals(perB.getName())) { System.out.println("perA == perB "); } } } // 这种形式在开发过程中不会出现,主方法需要出现的逻辑太多了 方法2 类方法自带比较方法 compare() classPerson { private String name ; private int age ; public Person(String name, int age) { this.name = name ; this.age = age ; } public String getName() { return this.name ; } public int getAge() { return this.age ; } //this表示当前对象,另外一个是传入对象 public boolean compare(Person per) { if (per == this) { return true; } if (per == null) { return false; } if (this.name.equals(per.name)&& this.age == per.age) { return true; } else { return false; } } } publicclass TestDemo2 { public static void main(String[] args) { Person perA = newPerson("A",20); Person perB = new Person("A",20); System.out.println(perA.compare(perB)); } } 判断步骤: 1. 判断地址 2. 判断是否为空 3. 判断对象的各个属性 课时39 引用传递实际应用 引用传递是java核心 合成设计模式 class Member { private String name; private int age; private Member child; //car == null, 说明此人无车 private Car car; public Member(String name, int age) { this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public String getName() { return this.name; } public void setAge(int age) { this.age = age; } public int getAge() { return this.age; } public void setChild(Member child) { this.child = child; } public Member getChild() { return this.child; } public void setCar(Car car) { this.car = car; } public Car getCar() { return this.car; } public String getInfo() { return "[Member] name = " + this.name + "age = " + this.age; } } class Car { private String car; private double price; private Member member; public Car(String car, double price) { this.car = car; this.price = price; } public void setCar(String car) { this.car = car; } public String getCar() { return this.car; } public void setPirce(double price) { this.price = price; } public double getPrice() { return this.price; } public void setMem(Member member) { this.member = member; } public Member getMember() { return this.member; } public String getInfo() { return "[car] car = " + this.car + "price = " + this.price; } } public class TestDemo { public static void main(String[] main) { Member mem = new Member("A",30); Car car = new Car("car-a",100); Member child = new Member("B",2); Car childCar = new Car("car-b",200); mem.setCar(car); mem.setChild(child); car.setMem(mem); child.setCar(childCar); childCar.setMem(child); System.out.println(mem.getInfo()); System.out.println(mem.getCar().getInfo()); System.out.println(car.getMember().getInfo()); System.out.println(mem.getChild().getInfo()); System.out.println(mem.getChild().getCar().getInfo()); } } 课时40 【第03个代码模型】综合案例:数据表与简单Java类(一对多) /** 1. 先定义基本类,包括属性,构造函数,getInfo()函数 2. 定义各个类之间的关系,雇员的领导,部门里面的所有雇员,雇员属于哪个部门 3. 实现开发需求 (1) 设置类对象间的关系 (2) 获取数据 */ class Emp { private int empno ; private String ename ; private String job ; private double sal ; private double comm ; private Emp mgr ; private Dept dept ; public Emp() {} public Emp(int empno, String ename, String job, double sal,double comm) { this.empno = empno ; this.ename = ename ; this.job = job ; this.sal = sal ; this.comm = comm; } public void setMgr(Emp mgr) { this.mgr = mgr ; } public Emp getMgr() { return this.mgr ; } public void setDept(Dept dept) { this.dept = dept ; } public Dept getDept() { return this.dept ; } public String getInfo() { return "[Emp] empno = " + empno + " ename = " + ename + " job = " + job + " sal = " + sal + " comm = " + comm; } } class Dept { private int deptno ; private String dname ; private String loc ; private Emp[] emps; public Dept() {} public Dept(int deptno, String dname, String loc) { this.deptno = deptno ; this.dname = dname ; this.loc = loc ; } public void setEmps(Emp[] emps) { this.emps = emps ; } public Emp[] getEmps() { return this.emps ; } public String getInfo() { return "[Dept] deptno = " + deptno + " dname = " + dname + " loc = " + loc; } } public class TestDemo { public static void main(String[] args) { Dept dept = new Dept(10,"accounting","newyork"); Emp ea = newEmp(1,"A","Job-a",100.0,1.0); Emp eb = newEmp(1,"B","Job-b",200.0,2.0); Emp ec = newEmp(1,"C","Job-c",300.0,3.0); ea.setMgr(eb); eb.setMgr(ec); ea.setDept(dept); eb.setDept(dept); ec.setDept(dept); dept.setEmps(new Emp[] {ea,eb,ec}); System.out.println(dept.getInfo()); for (Emp emp : dept.getEmps()) { System.out.println("\t |-" +emp.getInfo()); if (emp.getMgr() != null) { System.out.println("\t\t |-" +emp.getMgr()); } } System.out.println(eb.getInfo()); if (eb.getMgr() != null) { System.out.println("\t |-" +eb.getMgr().getInfo()); } if (eb.getDept() != null) { System.out.println("\t\t |-" +eb.getDept().getInfo()); } } } 课时41 【第03个代码模型】综合案例:数据表与简单Java类(多对多) /** 基本信息: 学生表:编号,姓名,年龄, 课程表:编号,名称,学分 学生-课程关系表:学生编号,课程编号,成绩 需求: 1. 找到一门课程,参加此课程的所有学生信息和成绩 2. 找到一个学生,参加的课程的课程信息和成绩 设计过程: 1. 定义基本类,前2个表, 2. 第三个表是学生选课信息 3. 筛选关系,去掉第一步做的学生中的课程对象数组,取出课程中的学生数组,因为第二部中设计的表可以 表达关系了 4. 输出关系 */ class Student { private int studentId; private String studentName; private int studentAge; private StudentCourse[] studentCourse; public Student() {} public Student(int studentId, String studentName, intstudentAge) { this.studentId = studentId; this.studentName = studentName; this.studentAge = studentAge; } public void setStudentCourse(StudentCourse[] studentCourse) { this.studentCourse = studentCourse; } public StudentCourse[] getStudentCourse() { return this.studentCourse; } public String getInfo() { return "[Student] ID = " + this.studentId + " Name = " + this.studentName + " Age = " + this.studentAge; } } class Course { private int courseId; private String courseName; private int credit; private StudentCourse[] studentCourse; public Course() {} public Course(int courseId, String courseName, int credit) { this.courseId = courseId; this.courseName = courseName; this.credit = credit; } public void setStudentCourse(StudentCourse[] studentCourse) { this.studentCourse = studentCourse; } public StudentCourse[] getStudentCourse() { return this.studentCourse; } public String getInfo() { return "[Course] ID = " + this.courseId + " Name = " + this.courseName + " credit = " + this.credit; } } class StudentCourse { private Student student; private Course course; private double score; public StudentCourse() {} public StudentCourse(Student student, Course course, doublescore) { this.student = student; this.course = course; this.score = score; } public Student getStudent() { return this.student; } public Course getCourse() { return this.course; } public double getScore() { return this.score; } public String getInfo() { return //this.student.getInfo() //+ this.course.getInfo() //+ "[score] score = " + this.score; } } public class TestDemo { public static void main(String[] args) { Student a = new Student(1,"a",18); Student b = new Student(2,"b",19); Student c = new Student(3,"c",20); Course ca = new Course(1,"ca",10); Course cb = new Course(2,"cb",20); Course cc = new Course(3,"cc",30); a.setStudentCourse(new StudentCourse[] { new StudentCourse(a,ca,100.0), new StudentCourse(a,cb,100.0), new StudentCourse(a,cc,100.0) }); b.setStudentCourse(new StudentCourse[] { new StudentCourse(b,ca,90.0), new StudentCourse(b,cb,90.0), new StudentCourse(b,cc,90.0) }); c.setStudentCourse(new StudentCourse[] { new StudentCourse(c,ca,80.0), new StudentCourse(c,cb,80.0), //new StudentCourse(b,cc,90) }); ca.setStudentCourse( new StudentCourse[] { new StudentCourse(a,ca,100.0), new StudentCourse(b,ca,90.0), new StudentCourse(c,ca,80.0) }); cb.setStudentCourse( new StudentCourse[] { new StudentCourse(a,cb,100.0), new StudentCourse(b,cb,90.0), new StudentCourse(c,cb,80.0) }); cc.setStudentCourse( new StudentCourse[] { new StudentCourse(a,cb,100.0), new StudentCourse(b,cb,90.0) }); System.out.println("******************************"); System.out.println(a.getInfo()); System.out.println(b.getInfo()); System.out.println(c.getInfo()); System.out.println("******************************"); System.out.println(ca.getInfo()); System.out.println(cb.getInfo()); System.out.println(cc.getInfo()); System.out.println("******************************"); System.out.println(ca.getInfo()); for (int x = 0; x < ca.getStudentCourse().length;x++) { System.out.println("\t |- " +ca.getStudentCourse()[x].getStudent().getInfo() + "\n\t\t |- " +ca.getStudentCourse()[x].getInfo()); } System.out.println("******************************"); System.out.println(a.getInfo()); for (int x = 0; x < a.getStudentCourse().length; x++){ System.out.println("\t |- " +a.getStudentCourse()[x].getCourse().getInfo() + "\n\t\t |- " +ca.getStudentCourse()[x].getInfo()); } } } 课时42 【第03个代码模型】综合案例:数据表与简单Java类(角色与权限) 1. 进行单独类的描述 Dept //部门 Emp //员工 Role //角色 Privilege //权限 属性 构造函数 getInfo()函数 2. 进行关系的描述 一个部门有多个员工 ,且只有一个角色 员工只有一个部门 角色有多个部门,多个权限 权限有多个角色 角色-权限是2个外键(没有其他多的数据,上个例子有个成绩),不需要建表 3. 实现数据输出 创建部门数据,2个 创建员工数据,5个 创建角色信息,2个 创建权限数据,4个 部门和雇员 雇员和部门 部门和角色 角色和部门 设置角色和权限的关系 设置权限和角色的关系 4. 取出数据 完毕 class Dept { private int deptID; private String deptName; private Emp[] emps; private Role role; public Dept() {} public Dept(int deptID, String deptName) { this.deptID = deptID; this.deptName = deptName; } public void setEmps(Emp[] emps) { this.emps = emps; } public Emp[] getEmps() { return this.emps; } public void setRole(Role role) { this.role = role; } public Role getRole() { return this.role; } public String getInfo() { return "[Dept] deptID = " + this.deptID + " deptName = " + this.deptName; } } class Emp { private int empId; private String empName; private Dept dept; public Emp() {} public Emp(int empId, String empName) { this.empId = empId; this.empName = empName; } public void setDept(Dept dept) { this.dept = dept; } public Dept getDept(){ return this.dept; } public String getInfo() { return "[Emp] empId = " + this.empId + " empName = " + this.empName; } } class Role { private int roleId; private String roleName; private Dept[] depts; private Privilege[] privileges; public Role() {} public Role(int roleId, String roleName) { this.roleId = roleId; this.roleName = roleName; } public void setDepts(Dept[] depts) { this.depts = depts; } public Dept[] getDepts() { return this.depts; } public void setPrivileges(Privilege[] privileges) { this.privileges = privileges; } public Privilege[] getPrivileges() { return this.privileges; } public String getInfo() { return "[Role] roleId = " + this.roleId + " roleName = " + roleName; } } class Privilege { private int pId; private String pName; private String pFlag; private Role[] roles; public Privilege() {} public Privilege(int pId, String pName, String pFlag) { this.pId = pId; this.pName = pName; this.pFlag = pFlag; } public void setRoles(Role[] roles) { this.roles = roles; } public Role[] getRoles() { return this.roles; } public String getInfo() { return "[Privilege] pId = " + pId + " pName = " + pName + " pFlag = " + pFlag; } } public class TestDemo { public static void main(String[] args) { Dept deptA = new Dept(1,"财务部"); Dept deptB = new Dept(2,"技术部"); Dept deptC = new Dept(3,"行政部"); Emp empA = new Emp(1,"员工A"); Emp empB = new Emp(2,"员工B"); Emp empC = new Emp(3,"员工C"); Emp empD = new Emp(4,"员工D"); Emp empE = new Emp(5,"员工E"); Role roleA = new Role(1,"普通员工"); Role roleB = new Role(2,"高级员工"); Privilege PA = new Privilege(1000,"查询","正常"); Privilege PB = new Privilege(1001,"删除","正常"); Privilege PC = new Privilege(1002,"修改","正常"); empA.setDept(deptA); empB.setDept(deptA); empC.setDept(deptB); empD.setDept(deptB); empE.setDept(deptC); deptA.setEmps(new Emp[] {empA,empB}); deptB.setEmps(new Emp[] {empC,empD}); deptC.setEmps(new Emp[] {empE}); deptA.setRole(roleA); deptB.setRole(roleA); deptC.setRole(roleB); roleA.setDepts(new Dept[] {deptA,deptB}); roleB.setDepts(new Dept[] {deptC}); roleA.setPrivileges(new Privilege[] {PA}); roleB.setPrivileges(new Privilege[] {PA,PB,PC}); PA.setRoles(new Role[] {roleA,roleB}); PB.setRoles(new Role[] {roleB}); PC.setRoles(new Role[] {roleB}); System.out.println(empA.getInfo()); System.out.println("\t |-" +empA.getDept().getInfo()); System.out.println("\t\t |-" +empA.getDept().getRole().getInfo()); for (Privilege x :empA.getDept().getRole().getPrivileges()) { System.out.println("\t\t\t |-" +x.getInfo()); } System.out.println(roleA.getInfo()); for (Dept x : roleA.getDepts()) { System.out.println("\t |- " +x.getInfo()); for (Emp y : x.getEmps()) { System.out.println("\t\t|- " + y.getInfo()); } } System.out.println(PA.getInfo()); for (Role x : PA.getRoles()) { System.out.println("\t |- " +x.getInfo()); for (Dept y : x.getDepts()) { System.out.println("\t\t |- " +y.getInfo()); for(Emp z : y.getEmps()) { System.out.println("\t\t\t |- "+ z.getInfo()); } } } } } 课时43 static关键字(static属性) class Person { private String name; private int age; String country = "China"; public Person(String name, int age) { this.name = name; this.age = age; } public String getInfo() { return "[Person] name = " + this.name + " age = " + this.age + " country = " + this.country; } } public class TestDemo { public static void main(String[] args) { Person p1 = new Person("张三",10); Person p2 = new Person("李四",11); Person p3 = new Person("王五",12); System.out.println(p1.getInfo() + "\n" +p2.getInfo() + "\n" + p3.getInfo()); } } 以上country对象被重复保存了 需要把country变为共享属性 加static关键字 class Person { private String name; private int age; static String country = "China"; public Person(String name, int age) { this.name = name; this.age = age; } public String getInfo() { return "[Person] name = " + this.name + " age = " + this.age + " country = " + this.country; } } public class TestDemo { public static void main(String[] args) { Person p1 = new Person("张三",10); Person p2 = new Person("李四",11); Person p3 = new Person("王五",12); p1.country = "USA"; System.out.println(p1.getInfo() + "\n" +p2.getInfo() + "\n" + p3.getInfo()); } } /* E:\01_JAVA\project\java_basic\mldn\02\course_43>javacTestDemo.java E:\01_JAVA\project\java_basic\mldn\02\course_43>javaTestDemo [Person] name = 张三 age = 10 country = USA [Person] name = 李四 age = 11 country = USA [Person] name = 王五 age = 12 country = USA E:\01_JAVA\project\java_basic\mldn\02\course_43> */ 这样就不保存在堆内存中,而是保存在全局数据区的内存空间中,所有对象都可以对该数据区进行访问 此时代码可以通过一个对象修改,static要通过类名称直接调用,不要使用对象 语法 Person.country ="AA"; static属性不受实例化影响,创建对象前就可以操作 选择:是否选用static关键字 定义类99%的情况下不采用static属性 如果需要描述共享属性的概念,或者不希望收到实例化对象控制的时候,使用static 课时44 static关键字(static方法) 限制,语法规定: 所有的static方法不允许调用非static定义的属性和方法 所有的非static方法允许调用static定义的属性和方法 原因:所有的static方法可以再没有实例化对象的时候访问。 使用static方法的目的:某些方法不希望受到类实例化对象的限制。 课时45 static关键字(分析主方法) public static voidmain(String[] args) 主方法中定义方法的语法 public static 返回值 方法名(参数) 比如 public static void Print() { // } 如果没加static,那么就是类中的方法,需要实例化使用 public static voidmain(String[] args) public 表示公共,主方法作为程序起点,必须可以被公共使用 static 执行java程序的时候是类名称,不受实例化限制 void 主方法是起点,没有返回值 main 系统定义的方法名称 String[] args 参数,都是String 课时46 static关键字(static应用) 1. static对象的计数统计 class Person { private static int count = 0; public Person() { System.out.println( ++count ); } } public class TestDemo { public static void main(String[] args) { Person p1 = new Person(); Person p2 = new Person(); Person p3 = new Person(); } } 2. static实现 调用无参构造对属性做自动赋值,给属性自动命名 class Person { private String name; private static int count = 0; public Person() { this("NONAME - " + ++count); //调用本类有参构造 } public Person(String name) { this.name = name; } public String getName() { return this.name; } } public class TestDemo { public static void main(String[] args) { System.out.println(new Person().getName()); System.out.println(new Person("MLDN")); System.out.println(new Person().getName()); } } 总结: static属性和方法不是定义类的首要选择 static属性和方法不受类的实例化对象限制,可以直接通过类名称调用 课时47 代码块(普通代码块) 不重要的概念,清楚结构即可 使用{}定义的一段代码 1. 普通代码块 2. 构造代码块 3. 静态代码块 4. 同步代码块(多线程) 普通代码块: 定义在方法中的代码块 public class TestDemo { public static void main(String[] args) { {//代码块 int x = 10; System.out.println( "x = " + x); }//代码块 int x = 100; System.out.println( "x = " + x); } } 作用:避免变量重名 作用不大 课时48 代码块(构造块) 类中的代码块 class Person { {//构造块1 System.out.println("1"); } {//构造块2 System.out.println("2"); } public Person() { System.out.println("4"); } {//构造块3 System.out.println("3"); } } public class TestDemo { public static void main(String[] args) { new Person(); new Person(); } } E:\01_JAVA\project\java_basic\mldn\02\course_48>javaTestDemo 1 2 3 4 1 2 3 4 E:\01_JAVA\project\java_basic\mldn\02\course_48> 先会执行构造块,再执行构造方法 普通手段,没有什么意义,掌握概念即可 课时49 代码块(静态代码块) 使用static关键字定义的代码块 1. 非主类定义的 2. 主类中定义的 class Person { {//构造块1 System.out.println("1"); } {//构造块2 System.out.println("2"); } public Person() { System.out.println("4"); } {//构造块3 System.out.println("3"); } static {//静态块 System.out.println("5"); } } public class TestDemo { public static void main(String[] args) { new Person(); new Person(); } } 静态块优先于构造块执行 E:\01_JAVA\project\java_basic\mldn\02\course_49>javacTestDemo.java E:\01_JAVA\project\java_basic\mldn\02\course_49>javaTestDemo 5 1 2 3 4 1 2 3 4 E:\01_JAVA\project\java_basic\mldn\02\course_49> 用于static属性初始化 classPerson { private static String info ="hello"; {//构造块1 System.out.println("1"); } {//构造块2 System.out.println("2"); } public Person() { System.out.println("4"); } {//构造块3 System.out.println("3"); } static {//静态块 info += " world"; System.out.println(info); } } publicclass TestDemo { public static void main(String[] args) { new Person(); new Person(); } } E:\01_JAVA\project\java_basic\mldn\02\course_49>javacTestDemo.java E:\01_JAVA\project\java_basic\mldn\02\course_49>javaTestDemo helloworld 1 2 3 4 1 2 3 4 E:\01_JAVA\project\java_basic\mldn\02\course_49> 在主类中使用: publicclass TestDemo { static { System.out.println("*********************"); } public static void main(String[] args) { System.out.println("helloworld"); } } E:\01_JAVA\project\java_basic\mldn\02\course_49>javacTestDemo.java E:\01_JAVA\project\java_basic\mldn\02\course_49>javaTestDemo ********************* helloworld E:\01_JAVA\project\java_basic\mldn\02\course_49> 课时50 内部类的定义及使用(内部类基本概念) 暂时不作为首要的类设计原则 概念,一个类之内进行其他类结构嵌套的语法形式 class Outer { private String msg = "out"; class Inner { public void print() { System.out.println(msg); } } public void fun() { Inner in = new Inner(); in.print(); } } public class TestDemo { public static void main(String[] args) { Outer out = new Outer(); out.fun(); } } --- 程序结构混乱 好处:外部类对内部类的私有属性访问,内部类对外部类的私有属性访问 例子: 两个独立类,访问外部类的私有属性,会很复杂 class Outer { private String msg = "out"; public String getMsg() { return this.msg; } public void fun() { Inner in = new Inner(this); in.print(); } } class Inner { private Outer out; public Inner(Outer out) { this.out = out; } public void print() { System.out.println(out.msg); } } public class OuterDemo { public static void main(String[] args) { Outer out = new Outer(); out.fun(); } } 内部类的操作: 1. 内部类的访问需要通过外部类的方法完成,如果不想这么执行,那么需要进行实例化对象 外部类.内部类 内部类对象 = new 外部类().new 内部类(); 进行外部类的实例化是因为外部类中有普通属性,需要开辟空间,所以先new外部类 2. 不直接产生内部类对象 private class Inner() { // } 外部类需要创建方法 Inner in = new Inner() new Outer().fun() 3. 外部类当前对象的属性Outter.this.属性 课时51 内部类的定义及使用(static定义内部类) static定义,表示外部类的形式(结构和功能一样),这个内部类只能访问外部类中的static属性和操作 如果要操作外部类: 语法: 实例化对象: 外部类.内部类 内部类对象名称 = new 外部类.内部类(); 了解即可 课时52 内部类的定义及使用(在方法中定义内部类) 在方法中定义内部类的形式是最多的 问题:JDK1.8正常,之前的版本都是错误的 JDK1.7之前,如果方法中的内部类需要访问参数,参数必须使用final定义 编程中根据jdk版本决定是否加final 内部类使用暂时不作为首选 课时53 继承的定义与使用(继承问题的引出) 面向对象的第二个特点 在已有的基础上进行功能的扩充 消除结构定义上的重复 课时54 继承的定义与使用(继承的实现) extends 语法 class 子类 extends 父类 { } 子类可以直接继承父类的操作,属性和方法 扩充 课时55 继承的定义与使用(继承使用限制) 1. 子类对象在实例化前,先会实例化父类,调用父类的构造方法,再实例化子类,调用子类的构造方法 其实子类的构造方法隐含了super()方法 需要注意的是父类没有无参构造,那么super必须指定父类的构造方法 2. 只允许单继承,不允许多继承 一个子类只能继承一个父类 但是可以使用多层继承,一般建议3层最多 3. 进行继承的时候,子类会继承父类的所有结构。 私有属性,构造方法,普通方法 显示继承(直接调用) 操作父类的私有属性,隐式继承(setter和getter) 所有的private操作肯定无法直接使用 需要掌握: 1、继承的语法和目的 2、子类对象的实例化流程 3、继承的限制 扩展已有类的功能 ===== 代码重用 课时56 覆写(方法覆写) 重点核心 子类定义了与父类方法名称、参数类型和个数完全相同的方法,不能有比父类更严格的访问权限
进行复写使用的时候,需要关注 1、当前使用的对象是使用哪个类new的 2、调用方法如果被子类重写过,则会调用子类的方法 注意: 被复写的方法不能比父类有更严格的访问权限 private < default 父类中使用default权限,那么子类可以使用default/public 方法使用public 属性使用private 但是: 如果父类中使用private,子类中不能使用public,这样子类的中属于新方法,不属于复写 重载 复写 overloading override 重载:方法名称相同,参数类型和个数不同(返回值可以不同,但是开发规范建议不要) 在同个类中 无权限要求 复写: 方法名称,参数类型和个数,返回值都一样 在继承关系中提现 子类同个方法不能拥有比父类更严格的权限控制 课时57 覆写(属性覆盖) 子类定义了和父类 名称相同的属性 按照就近取用,取子类的属性 这个操作本身没有意义,因为属性都采用Private封装,且开发过程中不要使用重名属性 课时58 覆写(super关键字) super.方法() super.属性 子类调用父类 开发原则:在子类中使用父类方法和属性的时候,使用super super和this的区别 this: 访问本类中的属性和方法 先查找本类,如果本类没有则查找本类 表示当前对象 super: 访问父类中的属性和方法 不查找本类,直接找父类 1、子类复写弗雷德方法是因为父类的方法功能不足,才需要复写 2、方法复写的时候使用的是public权限 课时59 综合案例:数组操作(定义Array父类) class Array { private int[] data; private int foot; public Array(int length) { if (length > 0) this.data = new int [length]; else this.data = new int [1]; } public boolean add(int num) { if (this.foot >= this.data.length) { return false; } else { this.data[foot++] = num; return true; } } public class TestDemo { public static void main(String[] args) { Array array = new Array(5); } } class Array { private int[] data; private int foot; public Array(int length) { if (length > 0) this.data = new int [length]; else this.data = new int [1]; } public boolean add(int num) { if (this.foot >= this.data.length) { return false; } else { this.data[foot++] = num; return true; } } public int[] getData() { return this.data; } public void inc(int num) { int[] newData = new int[this.data.length + num]; System.arraycopy(this.data,0,newData,0,this.data.length); this.data = newData; } } public class TestDemo { public static void main(String[] args) { Array array = new Array(5); System.out.println(array.add(10)); System.out.println(array.add(9)); System.out.println(array.add(8)); System.out.println(array.add(7)); System.out.println(array.add(6)); array.inc(4); System.out.println(array.add(5)); System.out.println(array.add(4)); System.out.println(array.add(3)); System.out.println(array.add(2)); System.out.println(array.add(1)); for (int x : array.getData()) { System.out.print(x + ", "); } System.out.println(); } } 课时60 综合案例:数组操作(SortArray排序子类) class Array { private int[] data; private int foot; public Array(int length) { if (length > 0) this.data = new int [length]; else this.data = new int [1]; } public boolean add(int num) { if (this.foot >= this.data.length) { return false; } else { this.data[foot++] = num; return true; } } public int[] getData() { return this.data; } public void inc(int num) { int[] newData = new int[this.data.length + num]; System.arraycopy(this.data,0,newData,0,this.data.length); this.data = newData; } } class SortArray extends Array{ //父类中没有无参数的构造方法,因此子类必须明确调用父类中的有参构造方法 public SortArray(int num) { super(num); } public int[] getData() { java.util.Arrays.sort(super.getData()); return super.getData(); //引用传递 } } public class TestDemo { public static void main(String[] args) { SortArray array = new SortArray(5); System.out.println(array.add(10)); System.out.println(array.add(9)); System.out.println(array.add(8)); System.out.println(array.add(7)); System.out.println(array.add(6)); array.inc(4); System.out.println(array.add(5)); System.out.println(array.add(4)); System.out.println(array.add(3)); System.out.println(array.add(2)); System.out.println(array.add(1)); for (int x : array.getData()) { System.out.print(x + ", "); } System.out.println(); } } 不同的子类要根据不同的需求进行扩写 课时61 综合案例:数组操作(ReverseArray反转子类) class Array { private int[] data; private int foot; public Array(int length) { if (length > 0) this.data = new int [length]; else this.data = new int [1]; } public boolean add(int num) { if (this.foot >= this.data.length) { return false; } else { this.data[foot++] = num; return true; } } public int[] getData() { return this.data; } public void inc(int num) { int[] newData = new int[this.data.length + num]; System.arraycopy(this.data,0,newData,0,this.data.length); this.data = newData; } } class SortArray extends Array{ //父类中没有无参数的构造方法,因此子类必须明确调用父类中的有参构造方法 public SortArray(int num) { super(num); } public int[] getData() { java.util.Arrays.sort(super.getData()); return super.getData(); //引用传递 } } class ReverseArray extendsArray { public ReverseArray(int num) { super(num); } public int[] getData() { int mid = super.getData().length/2; int head = 0; int tail = super.getData().length-1; for (int x = 0; x < mid; x++) { int temp = super.getData()[head]; super.getData()[head] = super.getData()[tail]; super.getData()[tail] = temp; head++; tail--; } return super.getData(); } } public class TestDemo { public static void main(String[] args) { ReverseArray array = new ReverseArray(5); System.out.println(array.add(10)); System.out.println(array.add(9)); System.out.println(array.add(8)); System.out.println(array.add(7)); System.out.println(array.add(6)); array.inc(4); System.out.println(array.add(5)); System.out.println(array.add(4)); System.out.println(array.add(3)); System.out.println(array.add(2)); System.out.println(array.add(1)); for (int x : array.getData()) { System.out.print(x + ", "); } System.out.println(); } } 课时62 final关键字 可以定义 类 方法 属性 1、定义类的时候不能有子类,不能继承 2、final定义的方法不能被子类复写 3、final定义的变量为常量,不能修改 全局常量的定义:标识符全大写 public static final intFINAL_INT = 0; 课时63 多态性 重要! 核心表现: 1、方法多态 方法的重载 方法的复写 2、对象的多态性 实现前提:方法覆写 [自动]对象的向上转型:父类 父类对象 = 子类实例; 例如int到double [强制]对象的向下转型:子类 子类对象 = (子类)父类实例; 例如 double到int double = (int)数据 不转型,例如String 向上转型的情况,父类不可以调用子类中的方法 只有强制转换到 向下转型 才可以调用子类的方法 【实际开发过程中用不到】不是所有的父类对象都可以向下转型,如果要实现向下转型,必须先向上转型, 否则会出现ClassCastException异常(两个不同的类发生转换) 判断后再转型: instanceof 语法: 子类对象 instanceof 类名称 返回boolean 对象多态性:子类和父类之间的转换 向上转型核心用途:接收参数的操作统一
向下转型:子类扩充方法的调用 以后的开发过程中不要出现向下转型 课时64 抽象类的定义与使用(抽象类基本概念) 实际项目开发过程中,子类继承的必须是抽象类 抽象类:基本类扩充了抽象方法(只声明,没有方法体) 抽象类会要求子类必须重写抽象方法,比普通类要规范,普通类继承的时候可以不重写方法 abstract关键字 使用: 抽象类无法直接实例化 1、所有的抽象类必须要有子类 2、抽象类的子类(不是抽象类)必须复写抽象类的全部抽象方法 ---方法复写要考虑权限问题,最好一直使用public方法,而且private和abstract不能同时修饰同一个方法 3、抽象类的对象可以通过多态性,利用子类实例化 另外一种实现方式:(A类的子类只有1个B),这种设计形式比较少,内部提供子类。 对封装性有好处,不作为开发首选。 课时65 抽象类的定义与使用(抽象类使用限制) 抽象类有构造方法,子类实例化的时候会先实例化父类 如果父类没有无参构造,那么子类要用super()指定父类的有参构造 另外一个问题: 程序输出为0 实例化操作: 1、类加载 2、对象实例化,空间开辟 3、调用构造方法,属性初始化 结论:如果构造方法没有执行,那么对象的属性都是其默认值 抽象类中允许不定义抽象方法,但是依然无法直接从抽象类实例化 抽象类不能使用final声明,抽象方法不能使用private定义 抽象类分为内部抽象类(可以使用static定义),描述为外部抽象类 课时66 抽象类的定义与使用(模版设计模式) 抽象类强制规定了子类的实现结构,更多情况下起到模板的作用 最具代表性的是:Servlet 1、抽象类单继承局限 2、抽象类的使用要通过子类实例化使用 课时67 接口的定义与使用(接口基本概念) 抽象类,避免单继承缺点就要使用接口 开发设计原则:使用接口优先 基本概念:一个抽象方法+全局常量的集合 语法:使用interface 接口命名前加大写的I 子类使用接口,可以实现多个接口,接口可以实现多继承的概念,关键字implements 如果子类不是抽象类,就需要重写接口中的所有抽象方法 接口之间的转化 一个子类继承了多个接口,通过子类实例化之后,接口之间可以互相转换 课时68 接口的定义与使用(接口使用限制) 1、接口里只能有public权限 以后编写接口的时候,接口的方法上需要加上public 2、一个子类要继承父类和多个接口的时候,要使用extends先,再跟上implements 3、一个抽象类可以使用多个implements继承多个接口,接口不能继承抽象类 三层继承,以后经常会见到的操作形式 4、一个接口可以使用extends继承多个父接口 5、接口可以定义一系列的内部接口,包括:内部普通类,内部抽象类,内部接口,其中使用static定义的接口 可以视为外部接口 课时69 接口的定义与使用(使用接口定义标准) 接口可以表示一个标准 三大核心应用 1、定义操作标准 2、表示能力 3、在分布式开发中暴露远程服务方法(设计的概念比较庞大)rest架构,必须会 接口是在类上的抽象 设计类之前先设计接口 课时70 接口的定义与使用(工厂设计模式) (重要!!) 中间人,避免和对象直接接触 主方法是客户端,对于程序的修改不应该影响到客户端的代码 interface IFruit { publicvoid eat() ; } class Apple implements IFruit { publicvoid eat() { System.out.println("吃苹果"); } } class Orange implements IFruit { publicvoid eat() { System.out.println("吃橘子"); } } class Factory { //不需要factory产生实例化对象 publicstatic IFruit getInstance(String cmd) { if("apple".equals(cmd)) { returnnew Apple(); } if("orange".equals(cmd)) { returnnew Orange(); } returnnull; } } public class TestDemo { publicstatic void main(String[] args) { if(args.length != 1) { System.exit(1); } IFruitfruit = Factory.getInstance(args[0]); fruit.eat(); } } 接口,有子类,有工厂类,工厂类获取子类对象 课时71 接口的定义与使用(代理设计模式) 必须学会 背诵结构! Proxy 两个子类共同实现一个接口,一个子类负责真实的业务实现,另外一个完成辅助真实主题的操作 接口:核心目的 子类1:核心实现 子类2:代理实现 子类2调用子类1 加上工厂模式 记住代理模式的结构 课时72 接口的定义与使用(抽象类与接口的区别) 优先选择接口,开发 抽象类可以加普通方法 抽象类: abstract class 抽象方法+普通方法+全局常量+全局变量+属性+构造方法 可以使用各种权限 子类使用extends继承抽象类 一个抽象类可以实现若干个接口 单继承 接口: interface 抽象方法+全局常量 只能选择public权限 子类利用implements继承接口 一个接口不能继承抽象类,但是可以通过extends继承多个父接口 一个子类可以继承多个接口 实际开发中,抽象类设计比接口复杂 要求掌握:定义接口+实现子类 结构体: 类,对象,抽象类,接口 现阶段看见接口,先考虑创建子类 1、开发先考虑接口,避免但集成的局限 课时73 匿名内部类 匿名类:抽象类和接口上实现 普通类也可以写匿名内部类,但是不要使用,因为继承要求都是抽象类 暂时不要话费过多精力在匿名内部类上 jdk1.8 匿名内部类有了改进 课时74 Object类(Object类简介) 重要的操作类,java除了Object类之外都是有继承关系的,默认继承Object父类 以下两种类的定义效果一致: class Message {} class Message extends Object{} 例子 开发过程中,Object类是参数的最高统一类型。 Object本身自带的一些方法: 提供无参构造:所有的子类实例化的时候需要调用父类的无参构造 (必须把Object中的方法都掌握) toString 取得对象信息 equals 对象的比较 课时75 Object类(取得对象信息) 直接输出对象的时候是对象的地址编码 默认输出对象调用的就是toString方法 得到对象地址(所有对象都具有的特征) 子类可以复写toString方法 public String toString() { } toString的核心目的在于取得对象信息。替换了简单java类中的getInfo方法 String是作为信息输出的重要数据类型,所有的数据类型和String一起的时候,使用+号变为字符串链接 而对象要变成字符串,要使用toString方法 结论:字符串是王道,都会向string转型 课时76 Object类(对象比较) 使用equals()方法 String类中复写了equals() 开发过程中,使用equals进行对象比较。 对象比较开发过程中比较少用 课时77 Object类(接收引用数据类型) Object可以接受任意的对象 可以接受所有的引用数据类型(数组,接口,类) 例子1:数组 例子2:接口,Object接受接口对象是强制规定 参数统一