面对对象程序设计(Object-oriented Programming,OOP)
抽象过程:底层机器>汇编语言(对底层机器的轻微抽象)>C/BASIC命令式语言(对汇编的抽象)
问题空间>>编程语言(面向过程/面向对象)>>解空间(机器模型)
Smalltalk面向对象语言五个特性:
万物皆对象:将对象视为奇特的变量,存储数据
程序是对象的集合,它们通过发送消息来告知彼此所要做的
每个对象都有自己的由其他对象所构成的存储
每个对象都拥有其类型:类class
某一特定类型的所有对象都可以接收同样的消息:多态
对象object(具体:描述客观事物的实体)-类(抽象:具有相同属性和方法的一组对象的集合)
类是多个对象进行综合抽象的结果,是实体对象的概念模型,而一个对象是一个类的实例。类定义了对象拥有的特征(属性)和行为(方法)
所有Java程序都以类class为组织单元
面向对象三大特征:封装encapsulation、继承inheritance、多态polymorphism
类:关键词class定义自定义的数据类型(引用数据类型)
[访问修饰符] class 类名{ //帕斯卡命名规则(类名首字母大写)
//类成员
属性--成员变量
方法--成员方法
}
属性:对象所拥有的特征在类中的表示
[访问修饰符] 数据类型 属性名;
方法:对象执行操作的行为(返回值|方法名|参数|方法体)
[访问修饰符] 返回类型|void 方法名称(参数类型 参数){//参数列表-形参
//方法体
[return 返回值;]
}
创建对象:类名 对象名=new 类名();//左边类名为对象数据类型,右边类名()为类的构造方法
使用对象:对象名.属性//引用对象的属性
对象名.方法名();//引用对象的方法
返回值类型 变量名=对象名.方法名(实参);
方法调用:直接调用;new对象调用
对象数组:每个数组元素就是一个对象,根据下标找到某个元素时,可以按照对象的使用方
法来使用该元素
成员变量(全局变量):直接在类中定义的变量,属于对象
成员方法:
//带参数有返回值的方法
public String work(int time){
return "...";
}
局部变量:定义在方法(包main方法)或结构语句中的变量
成员变量与局部变量的区别:
1. 应用范围:成员变量在整个类内都有效、局部变量只在其声明的方法内有效
2. 生命周期:成员变量属于对象,随着对象的创建而创建,随着对象的消失而消失
局部变量使用完马上释放空间
3. 存储位置:成员变量属于对象,存储在堆内,堆内的实体,当没有引用指向其时,才垃圾回收清理
局部变量存在栈内存中,当不在使用时,马上就会被释放。
4. 初始值:
成员变量它存储在堆中,如果没有赋初值,有默认值
1. 整数byte、short、int、long =0;
2. char='\uoooo';
3. boolean =flase;
4. String =null;
5. 类类型 =null;
6. 数组 =null;
局部变量,在栈内存中,必须给初始化值,必须手动初始化
内存分析:栈内存(存储引用)-堆内存(存储对象)
匿名对象:对象实体没有对应的变量名引用
new Car().run();//当对象对方法进行一次调用的时候使用匿名对象简化代码;
//可以将匿名对象作为实际参数传递进去
形参(形式参数:方法定义处参数)-实参(实际参数:方法调用处参数):数据类型、个数、顺序相同
方法传参:基本数据类型和引用数据类型内存分配和传参区别
1.基本数据类型传递的是值(拷贝),形参导致参数的变化与实参无关
2.引用数据类型传递的是地址,形参实参指向的是同一个对象,形参导致的变化影响实参
构造方法:默认构造方法、带参数的构造方法;主要作用是进行一些数据的初始化
//构造方法没有返回值;方法名与类名相同;手动编写构造方法会导致默认构造方法消失
[访问修饰符] 方法名([参数列表]){
//方法体
}
public class Student{
public Student(){//默认的无参隐式构造方法:Student()创建对象的时候执行
//代码
}
//手动编写带参构造方法:对属性进行初始化
public Person(String name1, int age1, int weight1) {
this.name = name1;
this.age = age1;
this.weight = weight1;
}
}
Student s1=new Student(); //调用构造方法
Person p1=new Person(“小明”,18,60); //构造方法重载
this关键字:当前对象
this.属性|普通方法
本类构造方法的调用:this(参数)//必须放在第一句
super关键字:指向父类
super(参数);//调用父类构造方法
super.父类属性|方法
构造方法重载:方法参数类型、顺序必须不同,与返回值类型和方法体无关
方法重载:在同一个类中;方法名相同,方便记忆;参数的个数或类型不同
//无参数的工作方法
public void work(){
}
//带参数的工作方法--重载
public void work(String contect){
}
static关键字(修饰符):实例变量/静态变量-实例方法/静态方法
内存分析:存储在方法区(静态数据共享区)
public class Person {
public String name;//实例变量
public static int age;//静态变量|类变量
public static int PERSON_LIVE;
public void show1(String name,int age){//实例方法
show2(name,age);//可以直接访问静态变量或方法
}
public static void show2(String name,int age){//静态方法|类方法
//不能使用this和super,不能直接访问实例变量或方法
//实例方法,可以调用静态变量或方法、实例变量或方法,但不能定义静态变量
System.out.println(name+age);
}
}
public static void main(String[] args) {//main方法--静态方法
Person p = new Person();
p.age = 16;
Person.PERSON_LIVE = 1;//类名.类成员
Person.show("aaa", 16);//调用静态方法
}
static{//当java虚拟机加载类时,就会执行该代码块
//静态代码块,对类的初始化操作
}
封装:将类的状态信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。
/* 封装的步骤 */
//1.修改属性的可见性,设为private
private int age;
//2.设置setter/getter()方法:用于属性的读写
public int getAge() {//给age赋值
return age;
}
public void setAge(int age) {//取age值
//3.设置属性的存取限制:对属性值的合法性进行判断
if(age < 0){
System.out.println("不能小于0");
return;
}
this.age = age;
}
继承和多态
继承:代码重用;只支持单根继承,即一个类只能有一个直接父类;根类Obejct
[访问修饰符] class <SubClass> extends <SuperClass>{
子类访问父类构造方法:super();super(name){
//继承条件下的构造方法:系统默认调用父类无参构造方法;子类构造方法通过
super显式调用父类的有参构造方法,执行父类相应构造方法,而不执行父类无
参构造方法
//super代表父类对象;在子类构造方法中调用且必须是第一句;不可以访问
父类中定义为private的属性和方法
}
子类访问父类属性:super.name
子类访问父类方法:super.print();
} //SubClass子类或派生类,SuperClass父类或基类
方法重写(父子类):方法名相同、参数列表相同、返回值类型相同或者是其子类、访问权限不能严于父类、不能抛出比父类方法更多的异常
方法重写与方法重载的区别:
比较项 | 位置 | 方法名 | 参数列表 | 返回值 | 访问修饰符 |
方法重写 | 子类 | 相同 | 相同 | 相同或是其子类 | 不能比父类更严格 |
方法重载 | 同类 | 相同 | 不相同 | 无关 | 无关 |
多态:同一个引用类型,使用不同的实例,而执行不同操作(JVM的动态绑定机制:重写后的方法)
JVM的静态绑定:成员变量、静态方法
向上转型:父类ude引用指向子类对象,自动进行类型转换
<父类型> <引用变量名>=new <子类型>();
Pet pet=new Dog();
pet.setHealth(20);//通过父类引用对象调用的方法是子类覆盖或继承父类的方
法;无法调用子类特有的方法
向下转型:将一个指向子类对象的父类引用赋给一个子类的引用(父类类型转换为子类类型);需强制转换
<子类型> <引用变量名> = (<子类型>) <父类型的引用变量>;
Dog dog=(Dog)pet;//将pet转换为Dog类型
dog.catchingFlyDisc();//执行Dog特有的方法
抽象类和接口
抽象方法:
[访问修饰符] abstract <返回类型> <方法名>([参数列表]);
抽象类:被abstract修饰;不能实例化;可以创建一个引用变量,其类型是一个抽象类,指向非抽象的子类实例;没有方法体;一旦类中出现抽象内容,保证其子类必须对其进行重写,约束规范作用
定义抽象类:
public abstract class 类名称{
修饰符 abstract 返回类型 方法名();
修饰符 返回类型 方法名(){
//方法体
}
接口:是一种能力,约定;没有构造方法,不能实例化的类型
定义接口:
public interface 接口名{
//接口成员,只允许是全局常量和公共的抽象方法;不能实例化
public static final value;//变量
public abstract void Method();//abstract可省略;默认public abstract
}
接口继承的语法:
[修饰符] interface 接口名 extends 父接口1,父接口2,……{
常量定义
方法定义
}
类实现接口:
public 类名 implements 接口1,接口2,…{//必须实现接口中定义的所有方法
实现接口中方法
普通方法
}
Paper paper = new A4Paper();//接口指向具体实现类的对象
包机制:
声明包:package 包名;// java源文件中第一条非注释性语句,一个源文件只能有一个包声明语句;
导入包:import 包的完整路径 //每个包都是独立的,顶层包不会包含子包的类;package
和import的顺序是固定的
命名包:package com|edu|net|org.research(部门名). project(项目名);//小写字母
包机制:src/code-/com/hfxt/xxx;类文件的管理;将一组功能相同的类放在同一个包下
JDK提供的基本包:java.lang(虚拟机自动引入)、java.util(提供一些实用类)、java.io(输入、输出)、java.sql(访问数据源)
访问控制(访问修饰符):public(不同包)>protected(子类)>default(同包)>private(同类)
Jar包:打包文件
jar tvf test.jar 显示jar文件中包含的所有目录和文件名大小,详细信息
jar xvf test.jar 解压test.jar到当前目录,显示详细信息
jar tvf rt.jar > d:\rt.txt 重定向查看jar文件内容
模板设计:
abstract class Runcode{//模版代码修饰为final,避免子类重写父类的模版代码
public final void Method(){
}
}
异常
java异常体系结构:所有异常类型都是Throwable类的子类,它派生两个子类:Error类和Exception类
Error类:表示仅靠程序本身无法恢复的严重错误
Exception类:由java应用程序抛出和处理的非严重错误; 异常层次结构的根类
运行时异常(RuntimeException及其子类)、Checked异常(非运行时异常)
NullPointException -- 空指针异常
ClassNotFoundException -- 不能加载所需的类
ArrayIndexOutOfBoundException -- 数组下标越界
InputMismatchException -- 得到的数据类型与实际输入的不匹配
IllegalArgumentException -- 方法接收到非法参数
ClassCastException -- 对象强制类型转换出错
Java异常处理机制:五个关键字(try、catch、finally、throw、throws)
try-catch-finally捕获异常:
try{
//执行可能产生异常的代码
}catch( Exception e){
//捕获异常
}finally{
//无论以上代码发生什么异常都会执行的操作
}
throws声明抛出异常:声明多个异常用逗号隔开
throw抛出异常:手动抛出异常
public static void divide() throws Exception{
throw new Exception(“描述信息”); //手动抛出并声明
}
自定义异常:JDK的异常类型不能满足程序需要
Java高级
集合框架和泛型
集合(对象容器):位于java.util包中,提供接口(虚线框)和实现类(实线框)
--|Collection: 单列集合;存储一组不唯一、无序的对象
---|List: 存储有序元素,可重复;存储一组不唯一、有序的对象
---|ArrayList: 数组实现, 查找快, 增删慢
---|LinkedList: 链表实现, 增删快, 查找慢
---|Vector: 数组实现, 但线程安全, 效率略低
---|Set: 存储无序元素,不可重复;存储一组唯一、无序的对象
---|HashSet
---|TreeSet
---|LinkedHashSet
--|Map: 键值对
---|HashMap:底层是哈希表数据结构,线程同步,不可以存入null键,null值,效率较低
---|TreeMap:底层是二叉树数据结构。可以对map集合中的键进行排序
---|HashTable:底层是哈希表数据结构,线程是不同步的,可以存入null键,null值
---|LinkedHashMap:
Collection接口>子接口:List(链表ArrayList|线性表LinkedList)-Set集(HashSet/ TreeSet)
/* Collection通用方法 */
增加:
add(Object) 将指定对象存储到容器中
addAll() 将指定集合中的元素添加到调用该方法和集合中
删除:
remove() 将指定的对象从集合中删除
removeAll() 将指定集合中的元素删除
修改:
clear() 清空集合中的所有元素
判断:
isEmpty() 判断集合是否为空
contains() 判断集合何中是否包含指定对象
containsAll() 判断集合中是否包含指定集合
equals() 判断两个对象是否相等
获取:int size() 返回集合容器的大小
转成数组:toArray() 集合转换数组
List集合特有方法:
增加:
void add(int index, E element) 指定位置添加元素
boolean addAll(int index, Collection c) 指定位置添加集合
删除:E remove(int index) 删除指定位置元素
修改:E set(int index,E element) 返回的是需要替换的集合中的元素
查找:注意IndexOutOfBoundsException异常、找不到返回-1
E get(int index)
int indexOf(Object o)
lastIndexOf(Object o)
求子集合:List<E> subList(int fromIndex, int toIndex) //不包含toIndex
ArrayList<E>:分配连续的存储空间的数组;遍历、随机访问元素效率高
boolean add(Object o) 列表末尾添加元素,起始索引位置从0开始
void add(int index,Object o) 指定索引位置添加元素
boolean contains(Object o) 判断列表中是否存在指定元素
boolean remove(Object o) 删除元素
int indexOf(Object obj) 返回元素在集合中出现的索引
LinkedList:链表存储方式;插入、删除元素效率高
数据结构:栈(先进后出:push()/pop())-队列(先进先出: offer()/poll())
void addFirst(Object o) 列表首部添加元素
void addLast(Object o) 列表末尾添加元素
Object getFirst()/getLast() 返回列表的第一个/最后一个元素
Object removeFirst()/removeLast() 删除并返回列表第一个/最后一个元素
descendingIterator() 返回逆序的迭代器对象
Vector:描述一个线程安全的ArrayList
void addElement(E obj) 在集合末尾添加元素
E elementAt( int index) 返回指定角标的元素
Enumeration elements() 返回集合中的所有元素,封装到Enumeration对象中
Enumeration 接口:
boolean hasMoreElements() 测试此枚举是否包含更多的元素。
E nextElement() 如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素
Iterator接口(迭代器):Itreable> Collection
Iterator<T> iterator()返回该集合的迭代器对象
boolean hasNext() 判断是否存在另一个可访问的元素
E next() 返回要访问的下一个元素
void remove() 移除迭代器返回的最后一个元素
List特有迭代器ListIterator(extends Iterator)
ListIterator<E> listIterator()
add(E e) 将指定的元素插入列表
void set(E o) 用指定元素替换next或previous返回的最后一个元素
hasPrevious() 逆向遍历列表,列表迭代器有多个元素,则返回 true
previous() 返回列表中的前一个元素
遍历集合:for循环;forEach;迭代器Iterator
//方法一:for循环
for(int i = 0;i < list.size();i++){
System.out.println(NewsTitle)list.get(i).getId());
}
//方法二:增强for
for(Object obj : list){
System.out.println(((NewsTitle)obj).getId());
}
//方法三:使用迭代器Iterator
Iterator iterator = list.iterator();
while(iterator.hasNext()){
Object obj = iterator.next();
System.out.println(((NewsTitle)obj).getId());//强制转换
}
Set接口:HashSet(hash表)-TreeSet(红-黑树)
HashSet(线程不安全,存取速度快。底层是以实现的)
HashSet检测重复:hashcode()和equals方法
TreeSet:红-黑树的数据结构,默认对元素进行自然排序
红-黑树:自平衡二叉查找树
红黑树基本操作(添加/删除):左旋-右旋
Map接口:存储一组键-值对(键集-值集),提供key到value(k-v)的映射
Hashtable-HashMap-TreeMap-LinkedHashMap
Map常见方法:
添加:V put(K key, V value) 可以是相同的key值,添加的value值会覆盖
putAll(Map<? extends K,? extends V> m) 从指定映射中将所有映射关系复制到此映射中
删除:remove() 删除关联对象,指定key对象
clear() 清空集合对象
获取:value get(key) 判断键是否存在的情况。当指定的键不存在返回null
判断:boolean isEmpty() 长度为0返回true否则false
boolean containsKey(Object key) 判断集合中是否包含指定的key
boolean containsValue(Object value) 判断集合中是否包含指定的value
长度:int size()
遍历Map:
Set<K> keySet() 返回所有的key对象的Set集合, 再通过get方法获取键对应的值
Collection<V> values() 获取所有的值,不能获取到key对象
Set<Map.Entry<k,v>> entrySet() //将map 集合中的键值映射关系打包成对象,Map.Entry对象的getKey,getValue获取其键和值
泛型Generic:把对象的类型作为参数,指定到其他类或方法上,从而保证类型转换的安全性和稳定性;可以约束集合内的元素类型
<T> 指定容器中元素的类型T(引用类型)
集合类<类类型> 变量名=new 集合类<类类型>();
泛型方法:public <泛型声明> 返回值类型 函数名(泛型 变量名)
public <T> T getT(T t) {}
泛型类:修饰符 class 类名<泛型>
pubic class Demo<T> {}
泛型接口:public interface Inter<T> {}
工具类(静态方法):Arrays(操作数组类)-Collections(操作集合类)
Arrays类:
binarySearch(int[])/binarySearch(double[]) 二分查找(数组需要有序)
void sort(int[])/sort(char[]) 数组排序
String toString(int[]) 数组转为字符串
copyOf() 复制数组
copyOfRange() 复制部分数组
equals(int[],int[]) 比较两个数组是否相同。
List asList(T[]); 将数组变成集合
Collections类:
二分查找:
int binarySearch(list,key);
int binarySearch(list,key,Comparator); list 集合中的元素都是Comparable 的子类
排序:
sort(list); //实际使用list对象的compareTo方法
sort(list,comaprator); //按照指定比较器进行排序
取集合最大值或者最小值
max(Collection)/max(Collection,comparator)
min(Collection)/min(Collection,comparator)
对list集合进行反转:reverse(list);
对比较方式进行强行逆转:Comparator reverseOrder()/Comparator reverseOrder(Comparator);
对list集合中的元素进行位置的置换:swap(list,x,y);
对list集合进行元素的替换:replaceAll(list,old,new);
可以将不同步的集合变成同步的集合:
Set synchronizedSet(Set<T> s)
Map synchronizedMap(Map<K,V> m)
List synchronizedList(List<T> list)
集合变数组: Collection 的toArray()方法
实用类
Java API:Java应用程序编程接口
java.lang包:Enum、包装类、Math、String、StringBuffer、System
枚举类enum:由一组固定的常量组成的类型
[Modifier] enum enumName{
enumContantName1
}
public enum Gender{
Male,Female
}
public class Student{
public Gender sex; //枚举类型的变量
}
Student stu = new Student();
stu.sex=Gender.Male;
Obeject类:所有类的父类; 所有的Java类都直接或间接继承类java.lang.Object类
常被子类重写的方法:toString()返回对象字符串、hashCode()返回该对象哈希码值
equals()比较对象内存地址、getClass()返回运行时类Class对象
// toString()源码
public String toString() {
if (isEmpty()) {
return "[]";
}
StringBuilder buffer = new StringBuilder(size() * 16);
buffer.append('[');
Iterator<?> it = iterator();
while (it.hasNext()) {
Object next = it.next();
if (next != this) {
buffer.append(next);
} else {
buffer.append("(this Collection)");
}
if (it.hasNext()) {
buffer.append(", ");
}
}
buffer.append(']');
return buffer.toString();
}
// equals()源码
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
包装类:基本数据类型-->包装类
Object->Boolean-Number(Byte/Short/Integer/Long/Float/Double)-Character
boolean -- Boolean char -- Character
byte -- Byte short -- Short
int -- Integer long -- Long
float -- Float double -- Double
集合不允许存放基本数据类型数据,存放数字时,用包装类
包装类构造方法:
public Type(type value) ex:Integer i=new Integer;
public Type(String value) ex:Integer i=new Integer(“123”);
// Number类型构造时,参数必须能转换为相应的数字,不然NumberFormatException
Boolean类型构造时,除了true(大小写),其它false
包装类常用方法:
***Value() -- 包装类转换成基本数据类型
toString() -- 以字符串形式返回包装对象表示的基本数据类型
parse***() -- 把字符串转换为相应的基本数据类型(Character除外)
基本类型转换为包装类:Integer intValue = new Integer(16);
包装类转换为基本类型:Integer integerId = new Integer(25);
int intId = IntegerId.intValue();
装箱和拆箱:基本类型和包装类的自动转换(JDK1.5以后)
Integer intObject=16; //装箱:基本类型转换为包装类的对象
int intValue=intObject; //拆箱:包装类对象转换为基本类型的值
String类(字符串常量):操作字符串,位于java.lang包中;
创建String对象两种方式:""直接赋值法、new关键字法
字符串连接: 使用”+”、String类concat()方法
内存分析:字符串常量池>栈内存(字符串名)>堆内存(字符串对象)
//字符串方法操作的变化都作用于字符串的副本本身无变化
//产生变化的方法:变大小写、连接、截取
获取方法:
int length() 获取字符串长度
char charAt(int index) 获取特定位置的字符(交付月结)
int indexOf(String str) 获取特定字符的位置
int lastIndexOF(int ch) 获取最后一个字符位置
判断方法:
boolean endsWith(String str) 是否以特定字符结束
boolean isEmpty() 是否为空(长度为0)
boolean contains(CharSequences) 是否包含指定字符序列
boolean equals(Object obj) 比较存储在两个字符串对象的内容是否一致
boolean equalsIgnoreCase(String str) 忽略大小写是否相等
equals()与==区别:一开始,equals()与==作用一致(比较两个字符串内存地址是否一致,是否为同一对象);后来,字符串对equals()方法进行了重写,equals()变成类比较两个字符串内容是否相等。
String s1="java";//s1,s2,s3都位于栈区
String s2="java";//s1,s2指向字符串池的同一个字符串”java”对象
String s3=new String("java");//创建两个”java”对象,但与串池重复,不用再放入串池中,且s3指向放入堆区的”java”对象
转换方法:
String(char[] value) 将字符数组转换为字符串
String(char[] value,int offset,int count)
String valueOf(char[] data)
String valueOf(char[] data,int offset,int count)
char[] toCharArray() 将字符串转换为字符数组
其他方法:
String replace(char oldChar,char newChar) 替换
String[] split(String regex) 切割
String substring(int beginIndex) 截取字符串
String substring(int beginindex,int endindex)
String toUpperCase() 转大写
String toLowerCase() 转小写
String trim() 去除空格
StringBuffer类:可变字符串缓冲区;对字符串频繁修改时,效率高于String
StringBuffer str=new StringBuffer(“content”);//String->StringBuffer
str.append(); //缓冲区的尾部追加字符串
str.insert(); //在指定的下标位置添加新的文本对象
str.toString(); //StringBuffer->String
str.reverse() //把字符串反序输出
StringBuilder类:与StringBuffer相似;单线程,线程不安全;效率更高
System(获取系统的属性)-Runtime(应用程序运行环境)
Date类(日期类)-Calendar类(日历类java.util.Calendar,封装年月日时分秒时区,)
String now=new SimpleDateForamte(yyyy-MM-dd HH:mm:ss).format(date); //格式转换
Math类:封装常用数学运算方法和两个静态常量E(自然对数底数)和PI(圆周率)
Math.abs()绝对值、Math.max()、Math.random()随机值
Random类:java.util.Random类
//用同一个种子值来初始化两个Random对象,每个对象调用相同方法,得到的随机数也是相同的
Random rand=new Random(int seed);
int num=rand.nextInt();
正则表达式(操作字符串的规则):匹配功能-切割功能-替换功能-获取(正则对象Pattern +匹配器Matcher)
str.matches(“正则表达式”)
预定义字符类:
. 任何字符(与行结束符可能匹配也可能不匹配)
\d 数字:[0-9]
\D 非数字: [^0-9]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 单词字符:[a-zA-Z_0-9]
\W 非单词字符:[^\w]
^ 行的开头
$ 行的结尾
\b 单词边界
\B 非单词边界
\A 输入的开头
\G 上一个匹配的结尾
\Z 输入的结尾,仅用于最后的结束符(如果有的话)
\z 输入的结尾
Greedy 数量词:
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好n次
X{n,} X,至少n次
X{n,m} X,至少n次,但是不超过m次
范围表示:
[abc] a、b 或 c(简单类)
[^abc] 任何字符,除了 a、b 或 c(否定)
[a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围)
[a-d[m-p]] a 到 d 或 m 到 p:[a-dm-p](并集)
[a-z&&[def]] d、e 或 f(交集)
[a-z&&[^bc]] a 到 z,除了 b 和 c:[ad-z](减去)
[a-z&&[^m-p]] a 到 z,而非 m 到 p:[a-lq-z](减去)
输入/输出I/O
文件(记录或数据的集合)-路径(相对路径/绝对路径)
File类:java.io.File包;文件的属性
File类的构造方法:
File(String pathname) 指定文件路径
File(String dir,String subpath) dir目录路径,subpath文件名
创建:
createNewFile() 在指定位置创建一个空文件,成功返回true,如果存在不创建然后返回false
mkdir() 在指定位置创建目录,只会创建最后一级目录,如果上级目录不存在就抛异常
mkdirs() 在指定位置创建目录,会创建路径中所有不存在的目录
renameTo(File dest) 重命名文件或文件夹,也可以操作非空的文件夹
删除:delete() 删除文件或一个空文件夹,如果是文件夹且不为空,则不能删除
判断:
exists() 文件或文件夹是否存在
isFile() 是否是一个文件,如果不存在,则始终为false
isDirectory() 是否是一个目录,如果不存在,则始终为false
isHidden() 是否是一个隐藏的文件或是否是隐藏的目录。
isAbsolute() 测试此抽象路径名是否为绝对路径名
获取:
getName() 获取文件或文件夹的名称,不包含上级路径。
getPath() 返回绝对路径,可以是相对路径,但是目录要指定
getAbsolutePath()获取文件的绝对路径,与文件是否存在没关系
length() 获取文件的大小(字节数),如果文件/文件夹不存在则返回0L
getParent() 返回此抽象路径名父目录的路径名字符串;如果没有指定父目录,则返回null
lastModified() 获取最后一次被修改的时间
文件夹相关:
staic File[] listRoots() 列出所有的根目录(Window中就是所有系统的盘符)
list() 返回目录下的文件或者目录名,包含隐藏文件
list(FilenameFilter filter) 返回指定当前目录中符合过滤条件的子文件或子目录
listFiles() 返回目录下的文件或者目录对象,包含隐藏文件
listFiles(FilenameFilter filter) 返回指定当前目录中符合过滤条件的子文件或子目录
I/O流:一组有序的数据序列;以先进先出方式发送信息的通道
输入/输出与数据源:源数据源--流--读-->程序
程序-->写--流--目标数据源
输入输出流是相对于计算机内存(程序): 文件-输入->内存-读 内存数据-写->输出-文件
Java流:字节流(InputStream|OutputStream)-字符流(Reader|Writer)
缓冲字符流 BufferedReader|BufferedWriter
序列流SequenceInputStream
按流向区分:输出流(OutputStream和Writer作为基类)
输入流(InputStream和Reader作为基类)
按处理数据单元分:
字节流(字节输入流InputStream基类和字节输出流OutputStream基类);8位字节流
字符流(字符输入流Reader基类和字符输出流Writer基类);16位Unicode字符流
InputStream类:常用子类FileInputStream,用于从文件中读取数据
int read()/read(byte[] b,int start,int len) -- 读取数据到字节数组b
void close() -- 关闭输入流
OutputStream类:常用子类FileOutputStream,用于向文件写数据
void write()/write(byte[] b,int start,int len) --字节数组b输出到输出流
void close() -- 关闭输出流
Reader类:常用子类BufferedReader,接受Reader对象作为参数,添加到字符缓冲区
int read()/read(char[] c,int off,int len) --从输入流读取保存到字符数组c
void close() -- 关闭流
Writer类: 常用子类BufferedWriter;数据缓冲到字符输出流
write(String str,int off,int len) --将str字符串输出到指定输出流中
void flush() -- 刷新输出流
void close() -- 关闭输出流
读写文本文件:
字节流:FileInputSteam和FileOutputStream
- 引入相关的类
- 构造文件输入流FileInputSteam对象:FileInputStream构造方法
构造文件输出流FielOutputSream对象: FileOutputStream构造方法
- 读取文本文件的数据 把数据写入文本文件
- 关闭文件流对象:fs.close()
字符流:FileReader和FileWriter
- 引入相关类:import.io.Reader/FileReader/IOException
- 创建FileReader对象:Reader fr=new FileReader(“D:\\Doc\\hello.txt”);
创建FileWriter对象:Writer fw=new FileWriter(“D:\\Doc\\hello.txt”);
- 读取文本文件的数据:fr.read();
写入数据:fw.write(“”);
- 关闭相关的流对象:fr.close();fw.close();
public class IODemo {
public static void main(String[] args) throws IOException{
/* 读 */
//1 创建流对象
FileInputStream fis = new FileInputStream("C:\\Doc\\hello.txt");
int data;
System.out.println("可读取的字节数:"+fis.available());
System.out.println("文件内容为:");
//2 循环读数据
while((data=fis.read()) != -1){
System.out.println(data+"");
}
//3 关闭流对象
fis.close();
try {
String str = "java";
byte[] words = str.getBytes();//字节数组
/* 写 */
//1 创建流对象,以追加方式进入文件
FileOutputStream fos = new FileOutputStream("C:\\Doc\\hello.txt",true);
//2 写入文件
fos.write(words,0,words.length);
System.out.println("hello文件已更新!");
//3 关闭流对象
fos.close();
} catch (IOException obj) {
System.out.println("创建文件时出错!");
}
}
}
BufferedReader和BufferedWriter:带有缓冲区的字符流
BufferedReader--FileReader BufferedWriter--FileWriter
构造方法:BufferedReader(Reader) BufferedWriter(Writer)
方法:Read() write() flush()
序列流(合并流):SequenceInputStream
构造函数:SequenceInputStream(InputStream s1, InputStream s2)
序列化-反序列化:ObjectOutput-ObjectInput
实现类:ObjectOutputStream- ObjectInputStream
序列化Serializable:将对象的状态写入到特定的流中的过程
对象(内存)-->流(二进制的字节序列)
反序列化:从特定的流中获取数据重新构建对象的过程
流(二进制的字节序列)-->java对象(内存)
/* 使用序列化保存对象信息 */
//1.实现Serializable接口
/*public class Student implements Serializable{
}*/
ObjectOutputStream oos = null ;
try {
//2.创建对象输出流:ObjectOutputStream
oos = new ObjectOutputStream(new FileOutputStream("C:\\myDoc\\stu.txt"));
//3.调用writeObject()方法将对象写入文件
Student stu = new Student(1,"java",10);
oos.writeObject(stu);
} catch (Exception e) {
e.printStackTrace();
} finally{
//4.关闭对象输出流
if(oos != null){
oos.close();
}
}
使用反序列化获取对象信息:
//1.实现Serializable接口
ObjectInputStream ois = null;
try {
//2.创建对象输入流: ObjectInputStream
ois = new ObjectInputStream(new FileInputStream("C:\\myDoc\\stu.txt"));
//3.调用readObject()方法读取对象 (反序列化,强转类型)
Student stu = (Student) ois.readObject();
} catch (Exception e) {
e.printStackTrace();
}finally{
//4.关闭对象输入流
if(ois != null){
ois.close();
}
}
反射
反射:在编译时不确定哪个类被加载,而在程序运行时才加载、探知、使用;动态获取信息以及动态调用对象方法的功能(.class文件->Class对象->类及属性方法)
Java反射(Java.lang.reflect):类(Class)-构造方法(Constructor)-属性(Field)-普通方法(Method)
- Class类:反射的核心类,可以获取类的属性、方法等内容信息
- Constructor类:表示类的构造方法
- Field类:表示类的属性,可以获取和设置类中属性的值
- Method类:表示类的方法,可以用来获取类中方法的信息或者执行方法
获取Class对象三种方式:Class.forName()、类名.class、对象.getClass()
forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装
反射操作:
通过Class类获取类型信息:
getName() 类的名称(全名,全限定名)
getSimpleName() 类的的简单名称(不带包名)
getModifiers(); 类的的修饰符
创建对象: newInstance() 无参数构造创建对象
获取指定参数的构造器对象,并可以使用Constructor对象创建一个实例
Constructor<T> getConstructor(Class<?>... parameterTypes)
通过Class类获取类型中方法信息:
Method[] getMethods() 获取公共方法包括继承的父类的方法,返回一个Method数组
getMethod("setName", String.class); 获取指定参数的公共方法
Method[] getDeclaredMethods() 获得所有的方法,包括私有
Method getDeclaredMethod(String name, Class<?>... parameterTypes) 获得指定参数的方法,包括私有
通过Class类获取类型中的字段的信息:
Field[] getFields() 获取公共字段
Field getField(String name) 获取指定参数的公共字段
Field[] getDeclaredFields() 获取所有的字段
Field getDeclaredField(String name) 获取指定参数的字段,包括私有
/* class对象创建的三种方式 */
//形式一 类.class
Class clz1=Person.class;
//形式二 对象.getClass()
Person p=new Person();
Class clz2=p.getClass();
//形式三 Class.forName()
Class clz2=Class.forName("cn.hfxt.reflect.Person");
// 动态创建其对象:根据class对象,动态调用默认构造创建真实Person对象.
Object obj = c1.newInstance();
//获取类中指定参数的构造方法对象.并动态调用此构造进行真实Person对象创建.
Constructor con= c3.getConstructor(String.class);
Object obj = con.newInstance("张三");
Constructor[] cons = c3.getConstructors();//获取其所有构造:
/*权限类: AccessibleObject : Constructor / Field / Method;
常见方法: isAccessible()
setAccessible(AccessibleObject[] array, boolean flag)*/
//动态操作对象的属性:根据反射得到class对象. 进行属性操作
//1.先得到一个class
Class c1 = Class.forName("cn.bdqn.clas.Person");
//2.class对象中的指定属性获取
//Field[] fs = c1.getFields();
Field f1 = c1.getField("name");
//3.创建真实对象,来进行属性操作.
Object p = c1.newInstance();
//给指定真实对象中的属性赋值
f1.set(p, "zhangsan");
//从真实对象中获取指定属性的值
Object nameValue = f1.get(p);
System.out.println( nameValue );
//动态操作对象的方法:根据反射得到class对象. 进行方法操作
//1.先得到Class对象.
Class c1 = Class.forName("cn.bdqn.clas.Person");
/*//形式一: 动态操作无参方法.
//2.Class中的指定方法获取.
Method m1 = c1.getMethod("show",null);
Object o1 = c1.newInstance();
//3.动态执行此方法.
m1.invoke(o1, null);*/
//形式二: 动态操作带参方法.
Method m1 = c1.getMethod("show2", String.class,int.class);
Object o1 = c1.newInstance();
//如果静态,需要真实对象o1. null就行.
m1.invoke(o1, "lisi",20);
注解和多线程
元数据:描述数据的数据
注解:Java代码的特殊标记;修饰程序元素(包、类、构造方法、方法、成员变量、参数、局部变量的声明)的形式化方法; 不影响程序代码的执行。
注解的类型是一个接口:程序可以通过反射来获取程序元素的注解对象;单独置于一行
不带参数的注解:@Annotation
带参数的注解:@Annotation({“参数1”,”参数2”,…”参数n”})
@MyTag(name=”Jack”,age=20)
内建注解(基本注解):定义于java.lang包中
限定重写父类方法:@Override
标记已过时:@Deprecated
抑制编译器警告:@SuppressWarnings(value=”unchecked/path/serial/all”)
元注解:@Retention @Target @Documented @Inherited
自定义注解:@interface
public @interface AnnotationTest{
//成员变量
String name() default “Jack”;
int age() default 20;
}
进程与线程
进程:应用程序的执行实例;有独立的内存空间和系统资源
线程:CPU调度和分派的基本单位;进程中执行运算的最小单位,处理机分配给线程,真正在CPU上运行的是线程
Java程序中:每个独立的小程序都是一个进程,而程序中main方法就是唯一的一个线程,
称为主线程;Java 虚拟机允许应用程序并发地运行多个执行线程
使用线程的步骤:定义线程>创建线程>启动线程>终止线程
1.创建线程的两种方式:
继承java.lang.Thread类:extends Thread
实现java.lang.Runnable接口:implements Runnable
2.重写run()方法
3.启动线程:start()而非run()
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
...
}
}
PrimeThread p = new PrimeThread(143);
p.start();
线程的生命周期:新生状态>可运行状态-阻塞状态>死亡状态
优先级:反映线程的重要或紧急程度(多个线程处于可运行状态)
线程的优先级用1~10(high)表示>更改优先级setPriority(int grade)
线程调度:join() -- 将指定的线程加入当前线程
sleep() -- 将当前线程阻塞指定的毫秒数
线程同步:同步方法(synchronized)、同步代码块(synchronized)
死锁:多个线程都处于等待状态而无法唤醒,就构成了死锁,此时处于等待状态的多个线程占用系统资源,但无法运行,因此不会释放自身的资源
网络编程技术
端口port(端口号)-IP地址(网络地址+主机地址)-DNS域名解析(域名系统)
网络服务器:客户机Client/服务器Server(C/S模式)-浏览器Browser/Server(B/S模式)
套接字Socket(两台机器间通信的端点;java.net包):
客户端Socket、服务器ServerSocket
流式套接字:基于TCP协议的Socket网络编程
TCP:面向连接;传输可靠;速度慢
数据包式套接字:基于UDP协议的Socket网络编程
UDP:面向非连接;传输不可靠;速度快
基于TCP协议的Socket编程:
Socket网络编程的步骤:(网络编程模型C/S)
服务器端:捕获一个Socket对象,进行解析
//1.创建服务器Socket -- 建立连接
ServerSocket serverSocket=new ServerSocket(5000);
//2.使用accept()方法等待客户的通信
Socket socket=serverSocket.accept();
//3.获得输入流,获得相应的用户请求 -- (输出流--装载数据 输入流--提取数据)
InputStream is=socket.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(is));
String info;
//数据流中读取信息
while((info=br.readLine())!=null){
System.out.println("客户端说:"+info);
}
//4.给客户端一个响应 -- 关闭所有的数据流和Socket
String reply="欢迎登陆!";
byte[] replys=reply.getBytes();
OutputStream os=socket.getOutputStream();
os.write(replys);
//5.释放相应资源
os.close();
br.close();
is.close();
socket.close();
serverSocket.close();
客户端:发送+接收
//1.创建客户端Socket
Socket socket=new Socket("localhost",5000);
//2.通过输出流发送请求
OutputStream os=socket.getOutputStream();
String info="用户名:TOM;密码:123456";
byte[] infos=info.getBytes();
os.write(infos);
//3.通过输入流接收到服务器给客户端的响应
socket.shutdownOutput(); //关闭输出流
InputStream is=socket.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(is));
String reply;
while((reply=br.readLine())!=null){
System.out.println("服务器的响应:"+reply);
}
//4.释放资源
br.close();
is.close();
os.close();
socket.close();
基于UDP协议的Socket编程:DatagramPacket
发送方:
//1.创建仓库,并负责装载数据
String info="使用Java高级实用技术";
byte[] buffer=info.getBytes("GBK");
InetAddress ip=InetAddress.getByName("127.0.0.1");
DatagramPacket packet=new DatagramPacket(buffer,
buffer.length,ip,9999);
//2.发送数据包
DatagramSocket socket=new DatagramSocket();
socket.send(packet);
//3.关闭
socket.close();
接收方:
//1.创建空仓库,并负责装载数据
byte[] buffer=new byte[1024];
DatagramPacket packet=new DatagramPacket(buffer,1024);
//2.接收数据包
DatagramSocket socket=new DatagramSocket(9999);
socket.receive(packet);
System.out.println(new String(packet.getData(),0,packet.getLength()));
//3.关闭
socket.close();
软件测试
白盒测试(结构测试或逻辑驱动测试)-黑盒测试(功能测试)-单元测试(方法测试)
Junit测试框架:junit3(extends TestCase)-junit4(注解的形式)
XML技术
XML(Extensiable Markup Language):可扩展标记语言
XML文档基本结构:
<元素名 属性名="属性值">元素内容</元素名> <!-- 属性值不能直接包含<、”、& -->
空元素:<name> </name> <name></name> <name/>
<?xml version=”1.0” encoding=”UTF-8”?> //声明
<!-- DTD验证xml -->
<!DOCTYPE books[
<!ELEMENT books (book*)>
<!ELEMENT book (author+,title+,description?)>
<!ATTLIST book ID CDATA #REQUIRED>
<!ELEMENT author (#PCDATA)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT description (#PCDATA)>
]>
<books> //根元素 文档元素描述信息(文档结构)
<!—图书信息--> //注释
<book id=”bk101”> //元素-属性
<author>bdqn</author>
<title>java</title>
<description>编程</description>
</book>
</books>
XML转义符(预定义实体):<(<)、>(>)、“(")、‘(')、&(&)
CDATA节:(元素中出现很多特殊字符)
<description>
<![CDATA[了解XML元素<title></title>的使用]]>
</description>
XML命名空间:
元素或者属性命名空间格式:xmlns:***=”URL”
默认命名空间:xmlns=”URL”
XML解析器:非验证解析器(格式是否良好) 验证解析器(DTD检查文档的有效性
DTD:文档类型定义,Document Type Definition;元素/元素之间关系/属性的定义规则
DTD文档的声明及引用:
内部DTD文档(Stu.xml):<!DOCTYPE 根元素 [定义内容]>
外部DTD文档(Stu.xml Stu.dtd):<!DOCTYPE 根元素 SYSTEM “DTD文件路径”>
内外部DTD文档结合:<!DOCTYPE 根元素 SYSTEM “DTD文件路径” [定义内容]>
DTD元素:<!ELEMENT NAME CONTENT>
关键字 元素名称 元素类型
元素类型:
EMPTY--空元素,该元素不能包含子元素和文本,但可以有属性 <!ELEMENT 人 EMPTY>
#PCDATA--可以包含任何字符数据,但是不能在其中包含任何子元素纯元素类型
<!ELEMENT 人 (#PCDATA)>
纯元素类型--只包含子元素,并子元素外没有文本
ANY--该元素可以包含任何在DTD中定义的元素内容
符号 | 用途 | 示例 |
() | 给元素分组 | (a|b|c),(a|d),a |
| | 在列出的对象中选择一个 | (A|B) |
, | 对象必须按指定的顺序出现 | (a,b,c) |
* | 该对象允许出现零次到任意多次(0到多次) | (a*) |
? | 该对象可以出现,但只能出现一次(0到1次) | (a?) |
+ | 该对象最少出现一次,可以出现多次(1或多次) | (a+) |
DTD属性:
<!ATTLIST 元素名称
属性名称 属性类型 属性特点
>
属性类型:CDATA、ID、IDREF/IDREFS、Enumerated
属性特点:#REQUIRED、#IMPLIED、#FIXED value、Default value
XML解析:DOM-SAX-DOM4J
DOM:基于XML文档树结构的解析;适用于多次访问的XML文档
文档对象模型(Document Object Model):把XML文档映射成一个倒挂的树(元素节点 属性节点 文本节点)
DOM解析的常用对象:Document文档,NodeList节点列表,Node单个节点,Element元素
DOM解析XML文件步骤:
- 创建解析器工厂对象,即DocumentBuilderFactory对象
- 解析器工厂对象创建解析器对象,即DocumentBuilder对象
- 由解析器对象对指定的XML文件进行解析,构建相应的DOM树,创建Document对象
- 以Document对象为起点对DOM树的节点进行增加、删除、修改、查询等操作
SAX:基于事件的解析;适用于大数据量的XML文档
DOM4J:非常优秀的Java XML API;开源
Document:文档 Element:元素 Attribute:属性 Text:文本节点
使用DON4J解析XML的步骤:
- 导入don4j的jar包,导入相应的类
- 指定要解析的XNL文件
- 把XML文件转换成Document对象
- 获取节点属性或文本值
解析xml文档:
- 通过SAXReader解析器读取File/InputStream获得Document对象
- Elemment root=Document对象.getRootElement;//获得根元素
- Element的常用方法:
element(“标签名”);//获得一个子标签
elements(“标签名”);//获得子标签List
elementIterater(“标签名”);//获得子标签Iterater
---------------------------------------------
getText();获得当前标签的文本内容
---------------------------------------------
attribute(“属性名”);//获得指定名称的Attribute对象
attributeValue(“属性名”);//获得指定名称属性的内容