码表:
ASCII:enter对应两个字符(\r\n),其他对应一个字符,每个字符占1字节
GB2312:应为占一个字节(正数),汉字占用两个字节(负数)
全角符号占2个字节,半角符号占1个字节
GBK:应为占一个字节(正数),汉字占两个字节(第二个字节可正可负) //这说明GB2312两个字节都是负的
unicode:所有字符占两个字节,前两字节是unicode特征码
UTF-8:每个字符占1~3个字节,英文占1个,汉字占3个,前3字节特是UTF-8的特征码
数据、方法:
引用数据类型都是对象
byte、short、char预案算是都会自动提升至int,称作表达式类型自动提升,是一种隐式类型转换
任何数字与字符串相加结果都是字符串
main函数必须静态,因为静态方法不能调用非静态方法
方法的返回值类型为void,此时不能用return返回值,但是可以用return结束调用
重载,同一个类中同名不同参数的函数,不限定返回值类型
取模运算中,模数的符号忽略,被模数的符号保留
while(true){x=(x+1)%10;} 完成x在0~9之间循环变化
instanceof:判断对象是否属于指定的类型
&& , || 短路运算
^ 任何一个数与一个指定的数异或两次,结果是自身。
不用中间变量交换两数的值,x=x^y;y=x^y;x=x^y;
移位运算不会改变变量的值
移位时会先将移动的位数对该类型所占位数取余
左移n位相当于乘以2的n次方、右移n位相当于除以2的n次方
流程控制:
switch中,default最好也加上break
switch中的参数必须是int,但byte,short,char也可以,因为会执行自动类型升级
break 标号,可以直接跳到某层循环,但不推荐这么做。最好采用改变循环变量的方式
读键盘判断是否输入……适合使用do...while
数组
数组时一种对象,凡是对象就会在堆内存开辟空间
stringbuffer的length()方法,而不是属性
数组的排序
选择排序,假设第一个最大,从后面所有的中找到最大的阈值交换。核心:先找最大数,再排序
冒泡排序,从后开始,两两冒泡,将最小的冒到前面
插入排序,每次把该位置上的数插到前面合适的位置(与前一个数作比较,效就换)
数据进制转换方法
Character.forDigit(数,要转的进制);
数组函数:
System.arraycopy(源数组,源数组起始位置,目标数组,目标数组起始位置,个数)
数组排序 java.util Arrays.sort()
类
类是对象的抽象,对象是类的实例
this是一个对象的引用,谁调用指向谁
虚拟机在创建对象时会自动初始化变量
对象的声明周期,从创建至失去所有的引用
如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象
在构造函数中可以用 this(实参) 来调用自己其他的构造函数,这种情况必须出现在第一行。一个构造函数中只能用this取调用一个其他的构造函数,注意不要产生递归调用
static
非静态的方法只能由对象来调用
静态方法内部不能使用this(因为静态方法不需要对象就可以使用,this没有获得引用)
静态代码块在类被加载的时候就执行了,一般进行初始化工作,只执行一次
静态变量的初始化和静态代码块的执行,顺序执行
类在第一次被使用时加载,且只加载一次
设计模式——单态、单例模式
整个软件的运行期间,针对某一个类只存在一个实例
实现方式:构造方法私有,定义变量记住实例。该变量私有,静态,定义静态方法返回该变量
内部类
引用方式 Outer.Inner inner=new Oter.new Inner()
内部类可以直接访问外部类的成员,外部类不能直接访问内部类的成员(这里注意说的是不能直接访问)
可以在方法中定义类,这样的内部类不能访问方法中定义的局部变量,除非这个变量被声明为final的
可以在方法中定义匿名内部类,匿名内部类为当前类名所表示的类的子类,一次性使用
static修饰静态内部类
非静态的内部类中不能声明静态成员
静态内部类中可以定义非static修饰的成员
静态内部类中不能访问外部非static的成员
继承
子类和父类之间的类型转换
向上转型:可以把一个子类当做父类来用,不可以把一个父类当做子类来用,可以定义一个父类类型的变量来记住子类对象,不需要强制类型转换,这就称为向上转型
强制类型转换:一个父类类型的变量指向子类对象时,不能用该变量取调用子类中定义的方法,可以将父类类型强转成子类类型,前提是父类变量指向子类对象。可以用instanceof先判断一下
什么情况下将子类当做父类来用
调用某个类的一个方法时,此方法声明需要一个父类对象,可以将一个子类对象作为实参传递过去,此时方法定义的形参是父类,在方法中使用父类变量调用方法时,其实是调用子类的方法
匿名内部类
定义子类,创建对象
对象的比较
不能用”==“,”==“是比较地址,应用equals方法,equals是object类的方法,所有的类都集成object类,返回一个布尔值——应当重写equals方法
@override告诉编译器线面的方法是重写父类的
覆盖父类的方法
覆盖方法和被覆盖方法具有相同的方法名称,参数列表和返回值类型
如果在子类中想调用父类中被覆盖的方法,可以用super.方法名的格式
覆盖方法不能使用比父类被覆盖方法更严格的访问权限
多态,把子类当做父类来用,针对父类进行方法调用,传入不同的子类,执行的结果完全不一样
final
final类不能被继承
final方法不能被子类重写
final变量(成员变量或局部变量)称为常量,只能复制一次
讲方法形参定义成final限定在方法中不能修改参数值
public static final修饰全局常量
子类实例化
instanceof关键字判断类型时会认为子类实例也属于父类类型
子类不继承父类的私有成员
构造函数不会被继承
子类对象实例化过程:
子类的构造方法中没有显示的声明调用父类哪个构造方法或自己其他的构造方法 的情况下,系统会自动调用一次父类无参的构造方法
子类第一行this其他构造方法则不自动调用父类的无参构造方法
构造方法中this和super只能出现一次,且必须在第一行
设计类时应定义一个无参的构造方法,不然子类实例化的过程就容易出错
在创建子类对象时,会调用子类的构造函数,在子类构造函数的第一行一定会调用父类的构造函数。不显示声明,调无参的,声明调用有参的则调用那个有参的构造函数
设计模式——组合
定义一个类需要用到另外一个类的方法时,就可以用组合,将用到的类定义为当前类的一个属性,铜鼓构造函数进行装配。
两者不构成继承关系。
继承应当时为了实现多态而存在,而不是为了方法的复用。
抽象类
没有方法体的方法必须要声明为abstract抽象方法
含有抽象方法的类必须要声明为abstract
抽象类不一定含有抽象方法
定义:用abstract修饰的类就是抽象类
抽象类不能被实例化
抽象类可以用extends关键字继承一个抽象类,会继承所有的方法
类可以继承抽象类,要实现抽象类中所有的抽象方法
什么时候使用抽象类:如果有多个类具有相同的方法声明,但实现不同,此时应定义抽象的父类,将方法在父类中定义。
继承关系3~4层为宜
如果一个类不想被实例化,可以使用声明为abstract的方法,即使它不包含抽象方法
设计模式——模板方法
定义一个抽象类作为模板,将具体做事情的方法定义出来,不实现
对外提供一个public方法作为借口,规定方法执行的流程,此方法为模板方法,应声明为final,禁止子类重写。
子类继承模板,实现所有的抽象方法
定义抽象类作为接口,可以实现模块间的解耦
反射:获得对象的类
接口
接口是一种特殊的抽象类,interface定义,没有方法体
接口里所有的方法必须都是抽象的
类implents实现接口,要实现接口中所有的方法
抽象类实现接口可部分实现方法或不实现
接口可以继承接口,用extends
通常使用匿名内部类来实现接口
extends要卸载implements前面
为了多态
接口中的方法默认public abstract、变量默认public final static,定义时必须赋初值
设计模式——策略模式
要完成一项功能,先不去直接完成,做一个借口,实现接口,在接口的实现中完成这个功能
可变参数:类型...形参
包
有包的类不能访问无包的类
jar
Java文件的压缩格式
用第三方的jar要将jar文件所在目录放入classpath(jar的绝对路径)
打jar:jar -cvf jar名 包名
运行jar:java -jar jar名
要加Main-Classjar才能运行,在MANIFEST.mf文件中设置
异常
e.printStackTrace()输出异常对象类名,异常信息,异常位置
system.out.println(e.toString())输出异常类名,异常信息
system.out.println(e.getMessage())输出异常信息
方法如果是用来调用的,最好抛出异常,不要处理
自定义异常
重写getMessage()就可以
方法遇到throw就结束
自定义运行时异常需继承RuntimeException
子类不能抛出比父类更多的异常
集合类
可以存对象、长度可变、可存放多种类型的对象
Collection接口
一个独立的元素的序列,单列集合的顶级父类
List集合,元素有序,先进先出,允许重复元素
Set集合,元素无序,不允许有重复元素
Map接口
一组成对键值对对象,双列集合的顶级父类,允许根据键查值
键不能重复,map的所有键构成一个set
Iterable
1.5开始,Collection父接口,实现增强的for循环
ArrayList线程不安全,底层是数组,增删慢,查找块
Vecter 线程安全
LinkedList 底层是链表,增删快,查找慢
add()添加
get()获取——因为有序
没有length,用size()方法
元素的迭代
|
Iterator |
Enumeration |
|
通过集合对象的iterator()方法获得 |
Vector可用 |
存在下一个 |
haxNext() |
hasNextElements |
获取下一个 |
next() |
nextElement() |
泛型:ArrayList al=new ArrayList();
集合一旦生命了泛型,便只能存储同一类型对象,迭代器也有泛型
增强的for循环:for(变量:集合)//这里的变量要是集合中的数据类型
可变参数只能被定义为函数的最后一个形参
Set
通过对象的equals方法保证没有重复元素
分为HashSet和TreeSet
HashSet
使用哈希算法保证没有重复元素
先调用对象的hashcode方法计算位置号,再用equals去重,存元素要正确重写object类的hashCode和equals方法
@Override
public int hasCode(){
return name.hashCode()*31+age; //这里据说hashCode*31会产生一个重复率很低的值
}
TreeSet
使用二叉树算法保证无重复,存储时排序
1、自然排序——实现了Comparable接口的compareTo()方法
2、在构造TreeSet对象时传一个比较器进去,比较器就是实现了CompareTo接口的compare方法
Map
存储:put(K,V)
要保证键的唯一性
可以通过建获得值,反过来不能
两种遍历方式:
1、keySet方法返回键的集合,迭代该元素获取所有键,用键get到值
2、entrySet方法返回键值映射的关系集合,迭代该集合获取每一对的键值映射关系,getkey取键,getValue取值
Map类总结:
HashMap
线程不安全,存取速度块,允许存null键null值,HashSet原理保证键的唯一性
Hashtable
线程安全,存取较慢,不允许null键null值,被HashMap所取代
TreeMap
二叉树算法保证键唯一性,对键排序,排序原理同TreeSet
Properties
HashTable的子类,线程安全,用于读写配置文件,键值都是String,不支持泛型。
特别:HashMap后存的同键名,键值会覆盖已存在的键值。
工具类
Arrays:数组常用操作
binarySearch:二分法查找,要求有序
Collections:集合常用操作
包装类
Integer 缓冲池1KB -128~127
Integer.parseXxx() 字符串转基类型
toString 基类型转字符串
自动拆装箱
系统类:
System类
exit() 退出虚拟机,0 无异常退出
gc() 垃圾回收
getProperties() 获取系统属性,获得后可以进行修改
in/out 标准输入流/输出流
Runtime类
getRuntime() 获取运行时实例
exec() 在后台窗口运行一条指令
时间对象
Date
new Date()创建时间对象代表当前系统时间
DataFormat类进行格式化
大多数方法已过时
Calendar
通过常量来表示时间的各种值
Calendar.getInstance
IO流
字节流的抽象基类:InputStream、OutputStream
字符流的抽象基类:Reader、Writer
由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀
IO程序的书写:
导入IO包中的类
进行IO异常处理
finally中对流进行关闭
Reader、Writer
一定要在finally中close()流
close()方法在关闭流之前会先调用flush()方法
追加,在构造方法的一个重载中boolean append 。true追加,默认false。
字符流-读取文件
建立一个流对象,将已存在的一个文件加载进流
FileReader fr=new FileReader(”Test.txt“);
创建临时数组
char[ ] ch = new char[1024]
调用流对象的读取方法读入数据到数组中
fr.read(ch);
定义文件路径时可用"/"或"\\"
创建文件时,如果目录下有同名文件会覆盖那个文件
读取文件时,保证该文件已存在,否则会抛出异常
字符流的缓冲区
BufferedWriter、BufferedReader
要结合流才可以实现,是对流的增强
是包装流,默认缓冲区8K
readLine() 读取一个文本行,过滤换行符
newLine() 写一个新行
设计模式——装饰/包装
对原有类进行功能的改变和增强
将被包装的对象组合进来,设计和原有对象一样的方法,在方法内取复用原有的对象
LineNumberReader跟踪行号的缓冲字符输入流
getLineNumber(),setLineNumber()
字节流
FileInputStream、FileOutputStream
可以操作其他媒体文件
字节缓冲流
BufferedInputStream、BufferedOutputStream
转换流(这也是种包装流)
InputStreamReader、OutputStreamWriter
字符流与字节流的转换
字节流中的数据都是字符时,转成字符流更高效
流的总结:
数据源可以是文件,也可以是键盘
数据的目的地可以是文件、显示器
字符流继承体系:
字符流
Reader Writer
BufferedReader InputStreamReader OutputStreamWriter BufferedWriter
FileReader FileWriter
FileInputStream FileOutputStream
字节流继承体系:
字节流
InputStream OutpuStream
FileInputStream FilterInputStream FileOutputStream FileOutputStream
BufferedInputStream BufferedOutputStream
File类
用来将文件或文件夹封装成对象
File对象可以作为参数传递给流的构造函数
创建了对象并不等于创建了文件
createNewFile()创建文件
文件不存在,成功创建,返回true
指定的文件已存在,返回false
创建失败,抛出IOException
常用方法
canRead()、CanWrite() |
是否可读、可写 |
delete() |
删除文件。用于删除目录时,只有目录为空才可以删 |
exits()、equals() |
是否存在、是否相当 |
getAbsolutePast() |
返回相对根目录的绝对路径名 |
getPath() |
对象封装的抽象路径名 |
getName() |
获取文件名 |
getParent() |
获取抽象路径 |
isAbsolute() |
是否使绝对路径 |
isDirectory() |
是否是目录,存在且是目录 返回true |
isFile() |
是否是标准文件 |
length() |
获得文件长度 |
mkdir() |
创建抽象路径名所表示的目录,只能创建一级 |
mkdirs() |
可以带不存在的父目录创建抽象路径名所表示的目录 |
list() |
便利文件,返回一个字符串数组 |
list(FilenameFilter filter) |
重写FilenameFilter的accept方法,用endWith方法实现 |
遍历出指定目录的所有文件和文件夹
1、调用ListFiles获得表示当前目录下所有文件的file对象组成的数组
2、遍历数组
3、打印每个file对象的绝对路径名
4、判断每个file,如果是目录,递归
目录拷贝
1、判断是否是目录
2、如果是,在目标目录下创建同名目录
遍历目录,递归,将目录下所有文件拷贝到新目录
3、如果是标准文件,在目标目录下创建同名文件,通过IO流进行文件拷贝
目录删除
1、判断是文件还是目录
2、如果是目录、遍历、递归
3、如果是文件,删除
打印流
PrintWriter(字符流)、PrintStream(字节流)包装了打印功能
.write() 输出一个字符
.print()会先自动包装基本数据类型
操作对象
ObjectInputStream(反序列化)、ObjectOutputStream(序列化)
ObjectOutputStream将java对象的基本数据类型和图形写入OutputStream
.writeObject()序列化对象到硬盘
对象的序列化:使用一种数据格式对对象进行描述,便于保存。序列化就是按照Java规定的格式将对象保存成一种数据,将数据格式转回对象,称之反序列化
序列流SequenceInputStream(这里要注意,没有序列输出流)
可以合并多个输入流,第一个流读完读下一个流,读到最后返回-1
操作基本数据对象,包装流
DataInputStream、DataOutputStream
从底层输入、输出流中读取、写入Java基本数据类型
完全等同于硬盘中的情况
操作内存缓冲数组,包装流
ByteArrayInputStream、CharArrayInputReader
available()估计可读字节数
管道流
PipedInputStream、PipedOutputStream
可对接,connect(PipedOutpusStream src)
RandomAccessFile 可读取可写入
反射 Reflection
获得对象运行时的类
获得类型的三种方式(Class的实例)
1、通过对象的getClass方法获得
2、通过表示类名的字符串来获得 Class.forname
3、明确的去获得那个类型
注意:void也是一种类型,也对应一个Class对象
或得类中定义的所有属性:getDeclaredFields();
setAccessible(true)取消Java编译器对该属性的访问权限语法检查
获得类中定义的所有方法:getDeclaredMethods()
获得类中定义的构造函数:getConstructors();
获得包名:getPackage()
返回修饰符:getModifiers() 返回一个int值,这个int值代表各修饰符常量的和
判断具体的修饰符:isPublic()等等