面向对象 Day01
====================
1 面向对象(OO)
1) 什么是Object(对象), Object 本意:东西,是指一个具体事物实例
2) 面向对象, 面向客观事物之间的关系.
4) OOA面向对象分析/OOD 面向对象设计
客人来了(来了一个客人类型的某人)
5) 面向对象概念
A 类型: 名词概念, 如: 客人, 菜品, 厨师
B 引用(变量): 引用具体概念实例的代词, 如: 某人, 特价菜
C 对象(东西): 具体概念的个体实例,如:张三丰这个人, 一盘大盘鸡
D 行为(方法)
E 多态: 行为/引用, 在具体情形下发生了变化的现象
一盏灯: 多态的
打: 根据宾语发生变化
F 封装: 任何对象实例都是尽可能封装, 减少暴露
E 继承: 概念的继承关系
2 Java 类型, 引用变量 与 堆对象
1)Java 类, 是用来描述事物类型的. 如: 书
<图书馆管理系统>中的概念: 书 Book
书的特征: 书号, 书名, 编号, 作者, 价格...
2) 类的声明:
public class Book{
long id;
String name;
String isbn; //书号
String[] authors; //作者
double price;
}
3) 引用变量与对象的创建过程:
A Java的内存管理与分配:
栈是一块Java使用内存区域, 使用的方式:LIFO(后来者居上) 堆也是一块Java使用内存区域, 使用方式: 无需随机分配
B 局部变量 与 堆对象空间分配
Java 局部变量在栈中分配, 是按照变量的类型分配
对象在堆中分配, 按照类的属性(实例变量)分配空间
C 变量类型与分配
变量分为: 基本类型和引用类型
基本类型变量的空间大小: 就是基本类型的空间大小, 值是基本类型 的值
引用变量的值是一个对象的地址值, 引用变量通过地址引用了一个堆 对象.引用类型变量的占用空间大小和值管理是"透明的(不可看见)",
由Java系统管理: 变量占用空间以及值的管理, 都是透明的.
4) 对象的属性默认自动初始化的. 自动初始化为"零"值, 引用为null
5) 在null引用上调用属性或方法, 会发生运行时异常
案例:
平面绘图坐标系中的一个点(Point),定义合理的属性
坐标是int类型.
O+-----------------------------> X
|
|
|
|
| . p(x,y)
|
|
|
|
Y
3 构造器(构造方法) 的作用: 用来描述对象的初始化过程的. 1)
如: 月饼实例的创建, 使用面和馅创建.
制作(构造器)
月饼模子(类) -----> 月饼(对象)
原料(构建参数)
点类型 --------> 原点
坐标(1,2)
2) Java中的构造器: 声明在类内部, 方法名与类名一致
的方法叫构造方法, 构造方法不能声明返回值类型.
构造方法可以包含参数, 参数一般是创建对象实例
必须依赖的条件(前提条件).
public class Point {
int x;
int y;
/** 构造器 */
public Point(int x, int y){
this.x = x;
this.y = y;
}
}
3) 对象实例化过程:
new运算: 创建对象实例
1 根据类的属性在堆中分配对象空间.并且自动初始化实例变量 2 根据参数类型调用构造器.
3 new运算返回对象的引用地址.
4) this 关键字
this 是对当前对象的引用, 是运行期间当前对象本身. 可以使用this明确的访问当前对象的属性或者方法 类似于"我".
this() 是调用本类的其他构造器, 可以使用构造器的重用, 简化代码的实现.
* this() 必须写在构造器的第一行!
5) 构造方法重载: 参数不一样的构造器
案例: Point.java
方法签名 = 方法名+参数类型列表
方法重载:a 方法名一样 b 方法参数不一样
也可以说: 方法名一样, 方法签名不同的方法
6) 默认构造器
1 java 类一定有构造器
案例: ConstructorDemo.java
2 如果类没有声明任何构造器,Javac自动提供一个
默认构造器, 无参数默认构造器
3 如果提供构造器声明, Javac将不再提供默认构
造器.
4 对象的方法
1) 表示对象的功能, 依赖于对象存在.
案例: Point.java
如: p1.distance() 和 p2.distance()
方法是动作,是功能,一般用动词声明.
2)方法也经常重载, 重载:方法名一样, 参数不一样重载体现了, 功能的多态.重载的方法经常互相重用.
Core Java Day02
====================
1 方法签名(方法的识别关键字)
方法签名 = 方法名+参数类型列表
Java 类中不能存在相同方法签名的方法
方法重载: 方法名一样, 方法签名不同的方法
char[] chs = {'A','B','C'};
int[] ary = {'A','B','C'};
System.out.println(chs);//ABC// println(char[])
System.out.println(ary);//[[@34ADCD//println(Object)
System.out.println(ary.toString());// [[@34ADCD
System.out.println('A');//A // println(char) 打印字符
System.out.println(65);//65// println(int) 打印整数
打人
打牌
方法重载就是: 动词的多意现象, 打人, 打牌, 打酱油, 打车
洗衣服, 洗手, 洗照片
保存联系人, 保存通话记录, 保存访问过的地址
save(Contact) save(Log) save(Url)
2 java方法参数的传递规则: 基于值的传递, 是变量值的 复制,
1) 基本类型就是其中值的复制,
2) 引用类型是引用值(地址)的复制.
案例: ParamaterDemo.java
* 变量的值: a 基本类型的值是其本身,
b 引用变量的值是一个地址值,是被引用对象的首地址. 为了避免引用参数传递的副作用, 建议一切结果使用
返回值带回.
3 继承 用来表达概念上具体化延续的具体概念.
1 * 子类继承父类的属性和方法
2 * 构造器不能继承!
3 实例化子类,会递归分配所有父类的空间
4 子类构造器一定调用父类构造器
* 类一定有构造器
4 关于继承中的构造器:
1 * 子类构造器中, 一定调用父类构造器。
2 子类构造器 默认调用父类无参数构造器!
3 如果父类没有无参数构造器,就必须在子类中明确指定调用 父类的有参数构造器!
4 使用super()调用父类构造器,必须写在子类构造器第一行 this() 必须写在子类构造器第一行
5 编程建议:所有的类都提供无参数构造器!减少继承时候的 麻烦。
5 关于对象的实例化过程:
1 检查类是否加载,如果没有加载就加载这个类,
要加载所有父类。(读取.class文件到内存)
* 懒惰式加载(按需加载):如果第一次用到就加载,
只加载一次。通过CLASSPATH指定的路径寻找类文件(.class), 加载以后是一个对象,类型是Class。
获得这个类对象:Student.class-> Class 实例
2 在内存堆中分配对象空间。递归分配所有父类和子类属性空间。 属性默认自动初始化。自动初始化为“0”值。
3 进行属性的赋值。
4 递归调用父类构造器。(默认调用父类无参数构造器!)
5 调用本类构造器。
6 访问控制修饰符
1 public
2 protected
3 default 很少使用,很少使用package作为访问控制的边界 4 private
* 一般自然现象: 都是尽可能的封装典型.
声明属性和方法尽可能私有。这样才能做到尽可能的封装。 提供适当的属性访问方法,适当的开放属性的访问。
一个源文件可以有多个类, 但是只能有一个public类,
文件名要与Public类一致. 如果有其他类, 就只能是默认修饰
不建议使用非公有类。就是说所有类都应该是公有的,并且 一个源文件一个类。
7 继承中的语法现象
1 父类型变量可以引用子类型的实例,父类型的实现是多态的! 2 子类可以覆盖父类的方法,修改父类的行为。
* 方法覆盖:子类覆盖了父类“相同方法签名”的方法。
方法的覆盖是由方法动态绑定实现的,就是Java虚拟机运行
时候确定执行那个那个对象那个方法,java最终执行子类的方法。
8 引用类型转换(是引用变量的类型的转换!)
1 向下转型(隐式/自动类型转换),是小类型到大类型的转换 如:
Circle c = new Circle(1,2,3);
Shape s = (Shape) c;//表示圆一定是图形
2 向上造型(强制类型转换),是大类型到小类型。 如:
Shape s = (Shape) new Circle(1,2,3);
Cirlcle c = (Circle)s; //当s实际引用圆时候,能够转换成功 s = new Rectangle(1,1,2,2);
Circle c2 = (Circle) s;//出现类型转换异常,因为
// s引用的是Rectangle 不是圆实例。
3 instanceof 运算符,用来检查引用对象的类型。
经常与“引用类型强制转换”配合,实现安全的类型转换, 避免类型转换异常
Day03
====================
1 Java Bean
关于JavaBean规范
1) JavaBean 不是语法规范,是习惯性编程规范,用这个规范 写的类使用方便。有时候JavaBean的类也称为:POJO Plan Old Java Object
2) 简化规范:
a 必须有包.
b Java类,具有无参数构造器。
c 有用getXxx() 和 setXxx() 声明的Bean属性。
如:getName() 和 setName(String n) 声明的
Bean属性为:name, 与是否有实例变量name无关. boolean类型的get方法可以有两种形式:
getMarried() 或者 isMarried()
d 必须实现序列化接口(在学习IO的时候具体学习。) e JDK提供的类几乎都符合JavaBean规范。
如:String
3) JavaBean 最大的好处:“使用方便”
2 static 静态 关键字, 修饰: 属性, 方法, 内部类, 代码块 static修饰的资源属于类级别, 是全体对象实例共享的资源 (属性, 方法, 内部类)
1) 静态属性, 使用static修饰的属性, 是在类的加载期间初始化 是属于类的, 全体类的实例共享的变量, 使用类名访问属性. 实例变量: 属于对象的属性.
2) static 方法, 使用static声明的方法, 属于类的方法, 一般
用来表示工具方法. 在类加载以后就可以自己调用, 不需要创建任何 类的实例.
3) 静态代码块,是在类加载期间运行的代码块,由于类只加载 一次,所以静态代码块只执行一次!
用途不是很常见,一般用来在类加载以后初始化一些静态资源 时候使用,如:加载配置文件。
4) 静态内部类(在内部类专题讲解)
3 final 最终的
1) final 修饰的类,不能再被继承。
Java 的String就是final类,不能被继承!
Math 也是final
Integer (包装类)
在实际项目开发中,原则上不允许使用final类!
Spring, Hibernate,Struts 2, 这个框架经常动态继承
代理我们的类。使用final的类可能造成这些框架的工作问题
2) final修饰的方法,不能再被覆盖。
在实际项目开发中,原则上不允许使用final方法!
3) final 修饰的变量,初始化以后不允许再修改了。
a final 局部变量
b final 方法参数
c final 的成员变量
4) final static -- Java使用final static修饰的变量作为常量。 一般要求常量名都有大写字母。
常量不是: const
4 abstract class 抽象类--不具体的类
1) 抽象方法,只有行为的概念,没有具体的行为实现。
使用:abstract 关键字修饰,并且没有方法体。
2) 包含抽象方法的类,就一定是抽象类。
使用: abstract 关键字修饰,包含抽象方法。
如:平面图形一定可以计算面积。
3) 抽象类不能直接创建实例。可以定义引用变量。
4) 抽象类只能被继承,一个具体类继承一个抽象类,必须实 现所有抽象方法。
5) 抽象方法和抽象类非常适合作为系统的分析和设计的工具。 public class abstract CRMSystem{
public abstract Client add(Client newGuy);
public abstract Event add(Event e, Client guy);
public abstract Event[] todayEvents();
}
5 接口, 相当于纯抽象类(cpp纯虚类)
1 接口:全部的方法都是抽象方法,全部的属性都是常量。 接口用来表示纯抽象概念,没有任何具体的方法和属性。 public interface CRMSystem{
Client add(Client newGuy);
Event add(Event e, Client guy);
Event[] todayEvents();
}
2 不能实例化,可以定义变量。
3 接口变量可以引用具体实现类的实例。
4 接口只能被实现(继承),一个具体类实现接口,必须使用全部的 抽象方法。
5 接口之间可以继承。
6 一个具体类可以实现多个接口,实现多继承现象,表示: 一个概念即是XXX也是XXX.
7 接口中的属性,默认是常量 public static final
8 接中的方法一定是:public abstract
9 实现一个接口,使用关键字implements, 实现实际上是 一种继承关系。接口和实现类是父子类型的关系
5 Object
1) Java 类默认继承于Object! 继承了Object 的属性和方法 如: toString(), hashCode(), equals()
2) toString() 方法, 经常有系统默认调用, 活动当前对象的 文本描述, Object默认返回: 全限定名@hashCode
建议覆盖为: 当前对象的文本描述
OOP Day04
====================
1 Object
1) Java 类默认继承于Object! -> 啥都是东西
继承了Object 的属性和方法
如: toString(), hashCode(), equals()
2) toString() 方法, 经常有系统默认调用, 活动当前对象的 文本描述, Object默认返回: 全限定名@hashCode
建议覆盖为: 当前对象的文本描述
3) equals 是用来比较两个对象是否相等的方法。
区别:引用相等 与 对象相等
引用值相等: 使用 “==”
对象的内容相等: .equals() 方法
equals在Object类中声明,默认的比较规则是:比较引用 建议覆盖,实现对象的比较(比较对象的状态,就是比较对象 的数据)。
* 覆盖规则:
a 自反性:对于任何非空引用值 x,x.equals(x)
都应返回 true。
b 对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y)
才应返回 true。
c 传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回
true,那么 x.equals(z) 应返回 true。
d 一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,
前提是对象上 equals 比较中所用的信息没有被修改。 e 对于任何非空引用值 x,x.equals(null) 都应返回 false。
4) hashCode()
A hashCode()方法要与equals方法一同覆盖
a 当两个对象equals比较为true时候,这两个对象应该 具有相同的hashCode()值
b 当两个对象equals比较为false时候,这两个对象应该 具有不相同的hashCode()值
c hashCode() 值要稳定(一致性),一个对象创建以 后就不应该再变化
B 默认的hashCode() 值是当前堆对象地址转换的一个整数 这个整数不是内存地址。
C 一般使用对象的OID值作为hashCode的值。
OID 对象的唯一编号,在工程项目中一般采用数据库来 生成OID,也就是数据库中的“主键”
2 String 字符串
String 字符串 = char[] + 操作(toUpperCase(), concat()) 类: 数据+相关的操作
char数组只是数据, 没有操作
一串字符就是字符串: char[] , String, StringBuilder
1 字符串"字面量(直接量)"都是String类型实例
"字符串常量"
public static final String TYPE = "car";
///////// 常量 字面量/直接量 Stirng 内部就是一个char[].
2 String API 有一个实现原则: 对象内容永远不变 也就是说: String对象永远不变.
3 String 字面量(直接量), 如果相同, 会替换为同 一个String对象的引用, 常量连接的结果也被优化 为一个字符串.
String s = new String("abc");
4 String 的比较, equals, hashCode()
5 String API (字符串的常用方法)
这些方法如果返回String 一般是一个新String对象 toString() 除外.
字符串中的字符有序号, 从0开始.
API 方法:
charAt()
length()
trim()
indexOf()
lastIndexOf()
endsWith()
startsWith()
substring(int start, int end)
substring(int start)
String str = new String(new char[]{'1','2','3'}); char[] chs = str.toCharArray();
3 正则表达式: 负责的字符串匹配处理规则, 应用广泛. 学习建议: 1 要能够读懂"正则表达式"
2 能够写出简单的"正则表达式" 3 不要过多的分配学习时间!
可以应用于: java grep vi
1 字符集: [1234] 表示 1,2,3,4 之一
[^12] 表示除了 1,2
[1-5] 表示 1,2,3,4,5
[a-f] 表示 a-f 之间的
[0-9a-fA-F] 表示:一个16进制字符
0[xX][0-9a-fA-F]{1,8}
[\w]{8,15}
预定义字符集:
\d : [0-9]
. : 任意字符
\w: 单词字符 [0-9a-zA-Z_]
\s: 匹配空白: \t \n \r \b \p
\D
\S
\W
2 {m,n} 数词
{n}
{m,n}
? : {0,1}
+ : {1,}
* : {0,}
3 ^ 开头
$ 结尾
邮政编码: ^[0-9][0-9][0-9][0-9][0-9][0-9]$
^[0-9]{6}$
^\d{6}$
用户名规则: ^\w{8,10}$
电话号: +86 139xxxxxxxx
^(\+86|0086)?\s?\d{11}$
身份证号码: ^\d{15}(\d{2}[0-9xX])?$
一个点的坐标: ^\d+(,\s*|\s+)\d+$
^\d+[,\s]\s*\d+$
答案规则:^\s*A?(\s+|,\s*)B?(\s+|,\s*)C?(\s+|,\s*)D?\s*$ 日期: 2011-01-30
^\d{4}-\d{2}-\d{2}$
^\d{4}(-\d{2}){2}$
IP 地址: 192.168.0.2
^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$ ^\d{1,3}(\.\d{1,3}){3}$
^(\d{1,3}\.){3}\d{1,3}$
String 对正则表达式的支持
.matches() 匹配正则表达式
.split("[,\s\|]") 切分字符串为字符串数组 .replaceAll()
Integer.parseInt() 转换到字符串到整数: 如: "23"-> 23
OOP Day05
====================
1 String 对正则表达式的支持
.matches() 匹配正则表达式
.split("[,\s\|]") 切分字符串为字符串数组
.replaceAll()
Integer.parseInt() 转换到字符串到整数: 如: "23"-> 23
2 StringBuilder 和 StringBuffer
String = char[] + 操作(复制创建新对象)
StringBuilder=char[] + 对char[]操作(处理当前数组内容) StringBuilder 内部的char[]数组内容可变, 如果长度
不够, 利用变长算法维护, 自动扩容长度.
1) StringBuilder 是变长字符序列
2) StringBuilder 方法:append,insert ... 都返回
当前 StringBuilder 对象本身的引用。
3) 如果软件需要大量字符串处理时候建议使用StringBuilder "A" + "B"
4) String s = s1+s2; Java实际上才是如下代码运行:
String s=new StringBuilder(s1).append(s2).toString();
String s = s1+s2+s3+s4; 被优化为
String s = new StringBuilder(s1)
.append(s2).append(s3).append(s4).toString();
s+="a";//会产生两个新对象(StringBuilder, String)
StringBuilder buf=new StringBuilder();
buf.append("a");
buf.append("a");
5) StringBuffer 和 StringBuilder API几乎一样!
StringBuffer 是java早期提供的,速度稍慢,线程安全 StringBuilder 是Java5 以后提供的,速度快,非线程安全
char[] Stirng StringBuilder(1.5) ==? StringBuffer(1.0)
非线程安全 非同步 线程安全 同步
3 线性表: List, 表示有先后次序的对象集合, 歌曲列表
ArrayList = Object[] + 线性表操作(增删改查)
StringBuilder = char[] + 操作(增删改查)
ArrayList(1.2以后新的) 是使用变长数组算法实现的 List (线性表方法)
Vector(1.0) 是使用变长数组算法实现是 List 矢量 向量
LinkedList 是采用双向循环链表实现的List
List 集合的实现
1 LinkedList 采用双向循环链表实现
2 ArrayList 变长数组算法实现 新的 快 非线程安全
3 Vector 变长数组算法实现 早期提供 慢 线程安全
4 线性表的应用
贪吃蛇
1 蛇是节点的(线性)集合,
节点在行列坐标(i,j)的位置
2 蛇可以走, 继续向当前方向走一步
也可以向指定方向走一步, 不能反向
蛇可以吃, 一个坐标上的东西.(以后再考虑)
3 蛇在一个面板中运行, 面板控制行列坐标
面板可以提供文字界面的打印方法, 显示出一条蛇 4 重构Worm类提供检查坐标是否在蛇身上的方法
5 提供测试类测试蛇的面板运行.
5 Map
1 HashMap 新
2 Hashtable 旧 (1.2以前)
散列表概念
1 容量: 散列表中散列数组大小.
2 散列运算: key->散列值(散列数组下标)的算法,
如: "mm".hashCode()%10->8
3 散列桶: 散列值相同的元素的"线性集合"
4 加载因子: 就是散列数组加载率, 一般小于75%性能比较理想 就是:元素数量/散列数组大小, 如: 7/10=70%
5 散列查找: 根据Key计算散列值, 根据散列值(下标)找到 散列桶,在散列桶中顺序比较Key, 如果一样, 就返回value 6 散列表中Key不同, Value可以重复