【笔记】阿里云大学Java面向对象开发课程笔记01-77课时
课时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 <score.length; a++){
System.out.print(score[a] +"\t");
}
System.out.println("");
}
System.out.print("最终排序结果:");
for(int a = 0; a <score.length; 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 <public
父类中使用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接受接口对象是强制规定
参数统一
【笔记】阿里云大学Java面向对象开发课程笔记01-77课时相关推荐
- [阿里云大学][Java面向对象开发][课程笔记][17-42课时]
课时17 数组的定义与使用(数组转置) 首尾交换 1. 新定义一个空数组,然后把原数组的值从后到前存入新的数组 问题:开辟了两块相同的堆内存空间,造成浪费 2. 在原数组上反转 计算数组长度/2,交换 ...
- 阿里云大学 Java编程入门(一)Java语言简介
Java语言简介 一.Java语言简介 1.1 认识Java(Java发展简介) 1.2 Java语言特点 1.3 Java可移植性 本系列内容为阿里云大学 java学习路线里的内容 阿里云大学 ja ...
- 阿里云大学-Java开发初级
下面的数据声明及赋值哪一个是正确的?( D ) A. float f = 1.3; B. char c = C. byte b = 257 D. int i = 10 MyBatis如何配置类型简称别 ...
- 利用阿里云搭建Java Web开发环境
安装jdk 查看yum源中的jdk版本 yum list java* 安装jdk1.8 yum -y install java-1.8.0-openjdk* 查看java的版本 java -versi ...
- 阿里云【名师课堂】Java面向对象开发57 ~ 59:覆写
阿里云[名师课堂]Java面向对象开发57 ~ 59:覆写 57:方法覆写 概念 访问权限 重载和覆写的区别 58:属性覆盖(了解) 59:super关键字 调用父类方法 调用父类属性 super与t ...
- 阿里云【名师课堂】Java面向对象开发2:面向对象简介
阿里云[名师课堂]Java面向对象开发2:面向对象简介 编程语言发展阶段 编程语言发展阶段 面向机器语言:汇编语言 面向过程语言:C语言.FORTRAN等 面向对象语言:Java等 面向过程的核心是编 ...
- 阿里云部署Java开发环境
阿里云部署Java网站和微信开发调试心得技巧(上) 本文主要是记录在阿里云服务器从零开始搭建Java执行环境并且部署web project的过程,方面以后查阅. 一.申请阿里云服务器 购买阿里云服务器 ...
- java公社博客_Java面向对象开发学习笔记(一)
Java面向对象开发 共105课时 课时1 面向对象简介 面向对象是一种程序设计方法,但是并不是所有开发者都认同面向对象,因为很多开发者认为面向对象过于复杂,所以更多人愿意使用函数式编程. 面向对象的 ...
- 阿里云趣味视觉AI训练营学习笔记Day 5
阿里云趣味视觉AI训练营学习笔记Day 5 学习目标 学习内容 前言 一.创建人像卡通化应用 二.应用配置 三.后端服务开发部署 四.小程序前端开发 阿里云高校计划,陪伴两千多所高校在校生云上实践.云 ...
最新文章
- $.ajax 的async参数在crossdomain跨站下的问题
- 【转帖】配置管理计划(CM Plan)
- onvif规范 中文介绍
- [html] 如何禁止input输入的历史记录
- 负载均衡会话保持技术、原理、产品(以F5为例)
- internetreadfile读取数据长度为0_Go发起HTTP2.0请求流程分析(后篇)——标头压缩
- 微信又可以发520红包,还新增情人节“撒狗粮”状态:律师提醒注意
- 针对自动化测试的23种Node.js优秀实践
- 马氏距离(Mahalanobis Distance)与欧式距离
- python中关于requests里的timeout()
- 《守望先锋》中网络脚本化的武器和技能系统
- [软件补丁]VS6 sp6补丁下载
- html中怎么引用jquery
- 2020 对自己好一点之新 Mac Book Pro 环境的安装
- oss :Request has expired.
- 小白终是踏上了这条不归路----小文的mysql学习笔记(1)
- JAVA调用有道API接口对数据库中的中文语句进行翻译
- Java常用集合List、Map、Set介绍以及一些面试问题
- 中国空间科学技术 参考文献
- Cause: org.apache.ibatis.ognl.OgnlException: source is null for getProperty(null, \“wname\“)\r\n\ta
热门文章
- 安装opencv踩坑笔记
- JT∕T 905 -2014 出租汽车服务管理信息系统的相关协议研究
- WiseBrowser 1.0震撼上市 创造移动浏览器巅峰神话
- 【error LNK1104】【无法打开文件opencv_core345d.lib 解决思路】
- 互联网思维(二)——流量时代,私域为王
- 高绩效团队的“八个一”特征
- 专享策略02 | 套利策略-自动换仓-出场加速
- rocketmq docker
- 解决SpringBoot项目中遇到的数据库连接yml文件配置问题
- Python图像处理(6):分离土壤与植物