1. Java是解释型语言:
java需要先编译为.class字节码文件,在执行时用解释器解释成操作系统能识别的文件。需要经过两次操作。
Java: 编译 *.java源代码文件---编译器编译---*.class字节码文件, 执行 *.class字节码文件----解释器解释----操作系统能识别的文件
C/C++: 编译 .C 源代码文件----编译器编译----*.exe字节码文件, 执行 *.exe字节码文件----操作系统能识别的文件。
2. 基础类型的包装类
基础类型分配到栈,引用类型分配到堆
基础类 包装类
int Integer
char Charater
boolean Boolean
…
转换:
1. 当需要把String 转换为基础数据类型时,使用对应的基础数据类型的包装类里面的方法。列:
int a = Integer.parseInt(s);
2. 将基本类型数据转换为String:
int a = 2;
String m = String.valueOf(a);
3. String转char:
String s = “Xforce”
char a = s.charAt(1);
重点:
1. 代码内存分析:
06_内存解析_1, 07_内存解析_2,08_内存解析_3, 14_TestCircle程序分析_1, 15_TestCircle程序分析_2, 15_TestCircle程序分析_2.
2. 动态绑定和多态
39_多态_1.avi 40_多态_2.avi 内存分析见39_多态_1.avi TestPolymoph\ Test.java
父类引用指向子类对象解释: 37_对象转型_1.avi
3. 抽象类、抽象方法
4. 接口
一、 对象和类的概念
1. 类是同种对象的集合与抽象,类中定义了这一类对象所应具有的静态和动态属性。
二、 面向对象设计思想和步骤:
(1) 分析问题中有哪些类那些对象
(2) 分析这些对象中应该具有的属性和方法
(3) 分析类与类之间的关系
三、 Java类的定义
四、 局部变和成员变量
局部变量:方法或语句块内部(方法的参数叫局部变量)(小)( 必须赋初试值才可以使用)
成员变量:方法外部、类的内部(大), 不用初始化,java系统会给你赋初始值
五、 引用类型(C中的指针,占两块内存)
六、 构造函数
构造函数是定义在java类中的一个用来初始化对象的函数
1. 构造函数名字与类的名字相同,大小写也保持一致
2. 使用new+构造方法创建一个新的对象
3. 构造函数与类同名切没有返回值。即便是void也不能写
4. 注意:当无指定构造函数时,编译器为类自动添加形为: 类名( ) { } 的构造方法
5. 例子:
public class Person{
int id;
int age = 20;
Person(int _id , int _age){
Id = _id
Age = _age;
}
}
七、 方法重载 OverLoad, 方法重写 OverWrite, 方法覆盖 Override
overload 完全新的方法,参数和原方法不同。
override 覆盖继承到的那个方法,原方法没有放弃。
overwrite 重写继承到的那个方法的代码,原方法被放弃。
其中Eclpise 中没有overwrite 的说法, 也即 override 和 overwrite是同一个概念。
马士兵教程: 方法覆盖Override也叫方法重写OverWrite。
方法重载OverLoad: 方法的重载指一个类中可以定义有相同的名字,但参数个数不同和参数类型不同的多个方法。调用时会根据不同的参数表选择对应方法.能被编译器区分的方法既是构成重载。构造函数(方法)也可以重载.
Person() {id = 0;age = 20;}
Person(int _id) {id = _id;age = 23;}
方法覆盖Override(方法重写OverWrite): 在子类中根据需要对基类中继承来的方法进行重写.
注意:1. 重写方法必须和被重写方法具有相同方法名称、参数列表和返回值.
2. 重写方法不能使用比被重写方法更严格的访问权限.
3. 子类覆盖父类的方法时,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,因为子类可以解决父类的一些问题,不能比父类有更多的问题.
4. 如果父类的方法是private类型,那么,子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法.
八、 this关键字
定义:在类的方法定义中使用this关键字代表使用该方法的对象引用
使用 this (argument_list) 调用本类的另外的构造方法
使用this.xxx = xxx 获取本类另外一个构造方法传来的值
this可以看做一变量,它的值是当前对象引用
九、 Static关键字
1. 在类中,使用static声明的成员变量为静态成员变量,它为该类的公用变量,在第一次使用时被初始化,对该类的所有对象来说,static成员变量只有一份。
2. 用static声明的方法为静态方法,在调用该方法时,不会将对象的引用传递给它,所以在static方法中不可访问非static的成员。
- ----静态方法不再是针对某个对象调用,所以不能访问非静态成员
3. 可以通过对象引用或者类名(不需实例化)访问静态成员。
4. 静态变量可以用来计数。(main方法可以直接调用)
十、 控制访问 public protected private default
1. 可修饰class和成员变量(成员方法)
2. Class: public和default
3. default 包权限
4. private私有类 子类拥有私有变量的所有权,无使用权(只能看 不能动)
十一、 类的继承与权限控制
Java中使用extends关键字实现类的继承机制。语法为:
通过继承,子类自动拥有了基类(父类)(superclass)的所有成员(成员变量和方法)
java只支持单继承,不允许多继承:一个子类只能有一个基类 一个基类可以派生出多个类
十二、 super关键字
用super来引用当前基类(父类)的成分 就是说子类继承父类时,父类的某个方法虽然完成的不是很好但是也完成了部分功能不必重写,就用super.f() 调用父类的相应方法,再接着写你想实现的功能
十三、 继承中的构造方法
1. 子类的构造过程中必须调用基类的构造方法。
2. 子类可在自己的构造方法中使用super(argument_list参数列表)调用基类的构造方法。
------如果调用super.必须写在子类构造方法第一行
------使用this(argument_list)调用本类另外的构造方法
补充:可以先用super()调基类,再用this()调子类,super()必须写在子类的构造过程前面!
---------http://orz.iteye.com/blog/64759
3. 如果子类构造方法中没有显示的调用基类构造方法则系统默认调用基类无参数的构造方法。
4. 如果子类构造方法既没有显示地调用基类构造方法,而基类中有没有无参数的构造方法,则编译出错。
5. 文件编译的时候,子类的所有方法都要执行一遍,即有参SubClass(int n){ }和无参的SubClass( ){}都要执行。
6. 更多: Java继承应用之小结 http://dbear.iteye.com/blog/641709
十四、 Object类之toString方法
1. Object类中定义有public String toString( )方法,起返回值是String类,描述当前对象的有关信息
2. 在进行String与其他类型数据的连接操作时(如:System.out.println(“info”+person)),将自动调用该对象类的toString()方法
3. 可以根据需要在用户自定义类型中重写toString()方法 TestToString.java
十五、 Object类之equals方法
1. 比较一个类两个对象的内容是否相等
2. Object的equals方法定义为:x.equals(y) 当x和y是同一个对象的引用时返回true否则返回false
十六、 对象转型
父类引用指向子类对象解释: 37_对象转型_1.avi
a instanceof Cat 判断a对象是不是Cat类型
十七、 动态绑定和多态
1. 在执行期间(非编译期)判断所引用对象实际类型,根据其实的类型调用其相应的方法
2. 多态存在的条件:有继承,有重写,父类引用指向子类对象。一旦满足,当父类里被重写的方法时,实际new的哪个子类对象,就调用子类对象方法。 见 笔记手册
总结:多态=继承+重写+父类引用指向子类的对象.
3. 父类引用指向子类对象
要理解多态性,首先要知道什么是“向上转型”。
我定义了一个子类Cat,它继承了Animal类,那么后者就是前者是父类。我可以通过 Cat c = new Cat(); 实例化一个Cat的对象,这个不难理解。
但当我这样定义时: Animal a = new Cat(); 这代表什么意思呢?
很简单,它表示我定义了一个Animal类型的引用,指向新建的Cat类型的对象。由于Cat是继承自它的父类Animal,所以Animal类型的引用是可以指向Cat类型的对象的。
那么这样做有什么意义呢?因为子类是对父类的一个改进和扩充,所以一般子类在功能上较父类更强大,属性较父类更独特, 定义一个父类类型的引用指向一个子类的对象既可以使用子类强大的功能,又可以抽取父类的共性。
所以,父类类型的引用可以调用父类中定义的所有属性和方法,而对于子类中定义而父类中没有的方法,它是无可奈何的; 同时,父类中的一个方法只有在在父类中定义而在子类中没有重写的情况下,才可以被父类类型的引用调用; 对于父类中定义的方法,如果子类中重写了该方法,那么父类类型的引用将会调用子类中的这个方法,这就是动态连接。
十八、 抽象类、抽象方法
1. 用abstract来修饰的类/方法
2. 规则:
1) 含有抽象方法的类必须被声明为抽象类,抽象类必须被继承,抽象方法必须重写
2) 抽象类不能被实例化
3) 抽象方法只需声明而不需实现
抽象类声明的语法形式为abstract class Number { . . .}
抽象方法声明的语法形式为public abstract
十九、 Final关键字
1. final 的变量的值不能够被改变
a) final 的成员变量
b) final 的局部变量(形参)
2. final 的方法不能够被重写
3. final 的类不能够被继承
如:public final class String 类
public final void m( ) 方法
final int I = 9 成员/局部变量
二十、 接口/interface
1. 接口是抽象方法和常量值的定义的集合
2. 从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。
3. 接口定义举例:
public interface Runner {
(public static final) int id = 1;
public (abstract) void start( );//抽象类,不需要实现
public (abstract) void run( );
public (abstract) void stop( );
}
4. 接口特征
1) 接口可以多重实现;
2) 接口中声明的属性必须为public static final的,可以不写;
3) 接口中只能定义抽象方法,而且这些方法必须为public abstract的;
4) 接口可以继承其他的接口,并添加新的属性和抽象方法;
5) 与继承关系类似,接口与实现类之间存在多态性*接口之间可以相互继承,类之间也可以相互继承而类只能实现接口对象实现接口的时候一定要把接口中的方法定义
接口实现:就是实现接口,实现接口里面的所定义的抽象方法
5. 接口规则
1) 多个无关类可以实现同一接口,如例二
2) 一个类可以实现多个无关接口,如例二
3) 与继承关系类似接口与实现类之间存在多态性
面向对象编程 基础重点如表对比
java中成员变量和局部变量的区别
比较项目 |
位置 |
作用范围 |
赋初值问题 |
修饰 |
定义 |
存储位置 |
分类 |
引用问题 |
局部变量 |
方法或语句块内部(方法的参数) |
小 方法体.语句块内部 |
必须手动初始化 |
不能被控制修饰符及static修饰 |
可以定义为final型 |
栈 |
|
所有类的成员变量可以通过this来引用。 |
成员变量: |
方法外部、类的内部 |
大 整个类体 |
自动初始化(被final修饰且没有static的必须显式赋值) |
能被控制修饰符及static修饰 |
可以定义为final型 |
堆 |
1实例变量 2类变量(static静态变量) |
|
Static
用Static声明的 |
叫 |
属性(特点) |
用处 |
位置 |
访问 |
变量(成员变量) |
静态成员变量 |
该类的公用变量,在第一次使用时被初始化,对该类的所有对象来说,static成员变量只有一份 |
计数 |
数据区 (data seg) |
类名.静态成员变量 |
方法 |
静态方法 |
在调用该方法时,不会将对象的引用传递给它,所以在static方法中不可访问非static的成员。 |
|
|
|
方法重载 OverLoad, 方法重写 OverWrite, 方法覆盖 Override
比较内容 |
定义 |
规定 |
例子 |
方法重载 OverLoad |
一个类中可以定义有相同的名字,但参数个数不同和参数类型不同的多个方法 |
能被编译器区分的方法既是构成重载 |
//构造方法重载 Person() {id = 0;age = 20;} Person(int _id) {id = _id;age = 23;} |
方法覆盖 Override, 方法重写 OverWrite |
子类中可根据需要对基类中继承来的方法进行重写(原方法被放弃,使用super()调用) |
1重写方法必须和被重写方法具有相同方法名称、参数列表和返回值 2重写方法不能使用比被重写方法更严格的访问权限 3.子类覆盖父类的方法时,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,因为子类可以解决父类的一些问题,不能比父类有更多的问题. 4. 如果父类的方法是private类型,那么,子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法. |
见下面
|
抽象&final
|
定义 |
规定 |
例子 |
|
Abstract |
抽象类 |
含有抽象方法的类必须被声明为抽象类 |
1抽象类必须被继承,抽象方法必须重写 2抽象类不能被实例化 3抽象方法只需声明而不需实现 |
Animal |
抽象方法 |
自己不实现方法(要定义,用abstract修饰),子类去实现方法。就是用来重写的 |
|||
Final |
变量 |
不能被改变 |
|
|
方法 |
不能被重写 |
|
|
|
类 |
不能被继承 |
|
|
接口
接口 |
定义 |
特点 |
规则 |
接口/interface |
抽象方法和常量值的定义的集合,特别地, 是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现 |
1接口中声明的属性必须为public static final的,可以不写; 2接口中只能定义抽象方法,而且这些方法必须为public abstract的;
|
1多个无关类可以实现同一接口,如例二 2一个类可以实现多个无关接口,如例二 3与继承关系类似接口与实现类之间存在多态性
|
访问控制
修饰符 |
类内部 |
同一个包 |
子类 |
任何地方 |
private |
√ |
|
|
|
default |
√ |
√ |
|
|
protected |
√ |
√ |
√ |
|
public |
√ |
√ |
√ |
√ |
栈内存 方法调用马上消失
堆内存 垃圾收集器来消除
Java中的异常处理机制的简单原理和应用:
当JAVA程序违反了JAVA的语义规则时,JAVA虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况。一种是JAVA类库内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会引发NullPointerException。另一种情况就是JAVA允许程序员扩展这种语义检查,程序员可以创建自己的异常,并自由选择在何时用throw关键字引发异常。所有的异常都是java.lang.Thowable的子类。
一、 一维数组
1. 数组可以看成是多个相同类型数据组合,对这些数据的统一管理
2. 数组变量属于引用类型,数组可以看成是对象,数组中的每个元素相当于该对象的成员变量
3. 数组中的元素可以是任何数据类型,包括基本型和引用类型
二十一、 二维数组
定义:二维数组相当于数组元素为元素的数组,例如 Int a[ ] [ ] = {{1,2},{3,4,5,6},{7,8,9} };
Java中多维数组的声明和初始化应按从高维到低维的顺序进行,即从左到右.
int a[ ][ ] = new int[ 3 ][ ];
二十二、 数组拷贝
使用java.lang.System类的静态方法:
Public static void arraycopy( Object src,int srcPos,Object dest, int destPos,int length)
可以用于数组src从第srcPos项元素开始的length个元素拷贝到目标数组从destPos项开始的length个位置。
如果源数据数目超过目标数组边界会抛出IndexOutOfBoundsException异常。
1. String
2. StringBuffer
3. 基础类型包装类
4. Math类
5. File类
6. Enum枚举类型
1136
1图:容器API类图结构图
1类:Collection类
3知识点:For Generic(泛型) Auto Boxing and Unboxing
6接口:Collection Set List Map Iterator Comparable
集合框架图
简化图:
容器API类图结构图(马士兵)
6个接口:
Collection接口: (一个一个的装):定义了存取一组对象的方法,其子接口Set和List分别定义了存储方式。
注意:重写equals方法必须重写hashCode方法(当一个类的某个对象当做索引(键),会使用hashcode方法)
两个对象互相equals则hashcode必须相等.
Set接口:其中的数据对象没有顺序并且不可以重复(两对象互相equals相等则重复), Set接口没有提供额外的方法. 与数学中”集合”的概念想对应.
HashSet(哈希集) Set接口的典型实现,按hash算法来存储集合中的元素。因此具有很好的存储和查找性能。HashSet判断两个元素的标准是两个元素的equals方法比较相等,同时两个对象的hasCode()方法返回值也相等。HashSet可以保存null元素。
LinkedHashSet: 是HashSet的子类,用法和HashSet一致。它们的不同之处在于LinkedHashSet是有序的,可以记住元素的插入顺序, 采用双重链接式列表.
SortedSet:是一个按照升序排列元素的Set接口的实现。
TreeSet(树集):
List接口:中的数据对象有顺序并且可以重复,类似数组(大小自动增加). List容器的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器总的元素。
ArrayList: 封装了一个自动增长容量的Object[]数组。所以ArrayList适合随机访问内部元素,而在列表中间添加删除元素的效率较低。ArrayList的常见方法都在List接口中。
1) 利用ArrayList的toArray()返回一个数组。
2) Arrays.asList()返回一个列表。
3) 迭代器(Iterator) 给我们提供了一种通用的方式来访问集合中的元素。
LinkedList:内部结构是线性链表,所以它适合从列表中间添加删除元素,而随机访问元素的效率较低。LinkedList类添加了一些处理列表两端元素的方法。
注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List:
List list = Collections.synchronizedList(new LinkedList(...));
Map接口:(一对一对的装):定义了存储“键(key) — 值(value)映射对”的方法. 键值不能重复。
HashTable: 继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。
HashMap:和Hashtable类似,不同的是HashMap是非同步的,并且允许null(null value和null key)
LinkedHashMap: LinkedHashMap扩展HashMap,以插入顺序将关键字/值对添加进链接哈希映像中。象LinkedHashSet一样,LinkedHashMap内部也采用双重链接式列表。
SortedMap:按照升序排列key的Map。
TreeMap:
Iterator接口 :用于遍历Collectin中的元素,相当于指针、游标,每一种容器有自己的Iterator接口。
Comparable接口:实现了这个接口的类,他们之间的对象可以互相比较大小.
Hash表
Hash表是一种数据结构,用来查找对象。Hash表为每个对象计算出一个整数,称为Hash Code(哈希码)。Hash表是个链接式列表的阵列。每个列表称为一个buckets(哈希表元)
集合框架实现类对照表:
实现类 |
接口 |
元素是否可以相同 |
有序/无序存储 |
基本数据结构 |
允许空值 |
线程同步(安全) |
效率 |
多用于 |
HashSet |
Set |
否 |
无序 |
Hash表 |
是 |
? |
|
|
LinkedHashSet |
Set |
否 |
有序 |
Hash表+双向链表 |
是 |
? |
|
|
ArrayList |
List |
允许 |
有序 |
动态数组 |
是 |
否 |
高 |
查询 |
Vector |
List |
允许 |
有序 |
动态数组 |
是 |
是 |
稍低 |
废弃(查询) |
LinkedList |
List |
允许 |
有序 |
链表 |
是 |
否 |
低 |
插入&删除 |
HashMap |
Map |
否 |
无序 |
Hash表 |
是 |
否 |
高 |
常用 |
HashTable |
Map |
否 |
无序 |
Hash表 |
否 |
是 |
稍低 |
|
3个知识点:
知识点1:JDK1.5增强For循环
知识点2:自动打包解包 (jdk1.5以后) Auto Boxing and Unboxing.
打包:自动将基础类型转换为对象
解包:自动将对象转换为基础类型
// m1.put("one",new Integer(1));
m1.put("one", 1);
知识点3 Generic泛型:在定义集合的时候同时定义集合中对象的类型
List
如何选择数据结构
衡量标准:读的效率和改的效率
Array读快改慢
Linked改快读慢
Hash两者之间
一、 重点比较
1. ArrayList与LinkedList区别(从数据结构考虑)与性能对比(读写数据)+Vector
1) ArrayList和Vector都是实现了基于动态数组的数据结构, 其中Vector使用了synchronized方法(线程安全) 通常性能上较ArrayList差; LinkedList基于链表的数据结构。
2) 对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3) 对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
4) 查找操作indexOf,lastIndexOf,contains等,两者差不多。
5) 随机查找指定节点的操作get,ArrayList速度要快于LinkedList.
另外:
ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
2. HashMap与HashTable是区别与性能对比
1) HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。
2) HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。
3) HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。
4) Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。
5) 最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。
6) Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。
两句话总结:
HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口
HashMap => 不同步、允许空键值、效率高;
Hashtable => 同步、非空键值、效率略低
二、 Vector、ArrayList和LinkedList
大多数情况下,从性能上来说ArrayList最好,但是当集合内的元素需要频繁插入、删除时LinkedList会有比较好的表现,但是它们三个性能都比不上数组,另外Vector是线程同步的。所以:
如果能用数组的时候(元素类型固定,数组长度固定),请尽量使用数组来代替List;
如果没有频繁的删除插入操作,又不用考虑多线程问题,优先选择ArrayList;
如果在多线程条件下使用,可以考虑Vector;
如果需要频繁地删除插入,LinkedList就有了用武之地;
如果你什么都不知道,用ArrayList没错。
三、 Vector、ArrayList和LinkedList总结
1) 如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。
2) 如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。
3) 要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。
4) 尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程.
分类:
1. 数据流的方向不同: 输入输出流(相对于程序来说)
2. 处理数据单位不同:字节字符流,
3. 功能不同: 节点流(直接读取写入..不经过处理), 处理流(进过处理的流)
|
字节流 |
字符流 |
输入流 |
InputStream |
Reader |
输出流 |
OutputStream |
Writer |
1. InputStream 继承自InputStream的流都是用于向程序中输入数据,且数据的单位为字节(8bit).
2. OutputStream 继承自outputStream的流都是用于程序中输入数据,且数据的单位为字节(8bit).
3. Reader 继承自Reader的流都是用于向程序输入数据,且数据的单位为字节(16bit).
4. Writer 继承自Writer的流都是用于程序中输入数据,且数据的单位为字节(16bit).
5. 节点流类型(直接读取写入..不经过处理)
典型代码
字节:
FileInputStream in = new FileInputStream( "F:\\Xforce.txt");
FileOutputStream out = new FileOutputStream("F:\\Xforce.txt");
while ((b = in.read()) != -1) {
out.write(b);
}
字符:
FileReader in = new FileReader("F:\\Name.txt");
FileWriter out = new FileWriter("F:\\Xforce.txt");
while ((b = in.read()) != -1) {
out.write(b);
}
6. 处理流( 经过处理的流)
经典代码:
缓冲流:常用
字符:
FileReader infile = new FileReader("F:\\Name.txt");
BufferedReader br = new BufferedReader(infile);
FileWriter outfile = new FileWriter("F:\\Xforce.txt");
BufferedWriter bw = new BufferedWriter(outfile);
String s = null;
while ((s = br.readLine()) != null) {// 读一行
bw.write(s);
}
bw.flush();// 全部取出缓冲区数据
bw.close();
br.close();
字节:
FileInputStream fis = new FileInputStream("F:\\Name.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("F:\\Xforce.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int c = 0;
while((c = bis.read()) != -1){
bos.write(c);
}
bos.flush();// 全部取出缓冲区数据
bis.close();
转换流:
字节转字符:
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\char.txt"));
InputStreamReader isr = new InputStreamReader(new FileInputStream("F:\\Name.txt"));
数据流:
DataInputStream
DataOutputStream
打印流:
PrintStream
PrintWriter
Object类:
ObjectInputStream
ObjectOutputStream
Java IO的一般使用原则:
一、按数据来源(去向)分类:
1、是文件: FileInputStream, FileOutputStream, FileReader, FileWriter
2、是byte[]:ByteArrayInputStream, ByteArrayOutputStream
3、是Char[]: CharArrayReader, CharArrayWriter
4、是String: StringBufferInputStream, StringReader, StringWriter
5、网络数据流:InputStream, OutputStream, Reader, Writer
二、按是否格式化输出分:
1、要格式化输出:PrintStream, PrintWriter
三、按是否要缓冲分:
1、要缓冲:BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter
四、按数据格式分:
1、二进制格式(只要不能确定是纯文本的): InputStream, OutputStream及其所有带Stream结束的子类
2、纯文本格式(含纯英文与汉字或其他编码方式);Reader, Writer及其所有带Reader, Writer的子类
五、按输入输出分:
1、输入:Reader, InputStream类型的子类
2、输出:Writer, OutputStream类型的子类
六、特殊需要:
1、从Stream到Reader,Writer的转换类:InputStreamReader, OutputStreamWriter
2、对象输入输出:ObjectInputStream, ObjectOutputStream
3、进程间通信:PipeInputStream, PipeOutputStream, PipeReader, PipeWriter
4、合并输入:SequenceInputStream
5、更特殊的需要:PushbackInputStream, PushbackReader, LineNumberInputStream, LineNumberReader
决定使用哪个类以及它的构造进程的一般准则如下(不考虑特殊需要):
首先,考虑最原始的数据格式是什么: 原则四
第二,是输入还是输出:原则五
第三,是否需要转换流:原则六第1点
第四,数据来源(去向)是什么:原则一
第五,是否要缓冲:原则三 (特别注明:一定要注意的是readLine()是否有定义,有什么比read, write更特殊的输入或输出方法)
第六,是否要格式化输出:原则二
线程基本概念 Runnable线程类接口
线程创建和启动
线程的调度好优先级
线程的状态控制 sleep join yield
线程同步synchronized wait notify/notifyAll
一、 线程基本概 :
1进程:一个独立程序的每一次运行称为一个进程。
执行进程是指进程里面主线程mian方法开始执行了(静态概念)。机器上运行的都是线程
2线程是一个程序不同的执行路径 是一个程序内部的顺序控制流)
main方法:一个主线程,主分支
3一个时间点上一个CPU只能有一个线程执行
进程与线程区别
每个进程都有独立的代码和数据空间,进程间的切换会有很大开销。
线程可以看成轻量级的进程 同一类线程共享代码和数据空间,每个线程有独立的运行栈个程序计数器,线程切换开销小。
多线程:在操作系统中能同时运行多个任务(程序)。
多线程:在同一个应用程序中有多个顺序流同时执行。
二十三、 线程的创建和启动
1实现Runnable接口(常用,能从其他类基础和实现其他接口)
设计一个实现Runable接口的类,根据需要重写run方法;
建立该类的对象,以此对象为参数建立Thread类的对象;
调用Thread类对象start方法启动线程,将执行权转交到run方法。
2继承Thread类(继承比较死,不能从其他类继承)
定义一个从Thread类继承的子类并重写其run方法。
然后生成该类的对象,调用Thread类对象start方法启动线程。
二十四、 线程状态及转换
From Java Web开发详解
二十五、 线程控制基本方法
Sleep/Join/Yield方法 Sleep/Join(需要捕获异常)
二十六、 线程优先级 Priority
t1.setPriority(Thread.NORM_PRIORITY + 3);
二十七、 线程同步
同步的原理:
其实就是使用锁机制(synchronized, 最好只锁定一个对象)。
将多条操作共享资源的代码进行同步的封装,并加了锁。
只有获取到锁线程才可以进入到同步中,这时其他线程即使获取到执行权。
因为没有了锁,它们都进不来。这样就保证了数据的安全。解决了线程安全问题。
什么代码需要定义到同步中呢?
只有操作了共享数据的多条代码才放到同步中。
---读写两方法,写的方法加锁。
---两个方法都改了同一个值,两个方法都应该加同步.
同步的好处:解决了线程安全问题。
同步的弊端:对资源是一种耗费,相对降低效率。
同步的前提:
1,必须是两个或者两个以上的线程才需要同步。
2,多个线程必须使用同一个锁,才可以成为这些线程被同步了。
解决思想:在一个时间段,对于多条执行共享资源的语句,必须由一个线程执行完。
在执行过程中,其他线程不可以参与。
总结:造成安全隐患的因素
1,多个线程在操作共享资源。
2,有多条操作共享资源的代码。
---- http://bbs.itheima.com/forum.php?mod=viewthread&tid=2019
死锁: 两个或者两个以上的线程请求相互的资源,相互都不能释放形成死锁。
当m1()方法执行的过程中,另外的线程能执行m2().
重点(面试题):
1. 同步的实现有两种方法:
1. synchronized 方法和 synchronized 块
理解:锁定执行这个方法时当前这个对象。Sleep也有这个对象锁
2. synchronized + Wait + notify(notifyAll)
public synchronized void push(WoTou wt) {
while (flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
}
理解:wait() 锁定 当前访问这个对象的线程。释放对象锁, notify ()叫醒一个wait在当前对象的线程.
2. Sleep与wait方法比较
1. Sleep是线程类(Thread)的方法, 指线程暂停执行指定时间。但是不释放对象锁,别的线程不可以访问锁定对象。需要捕获异常。可以再任何地方使用。
2. Wait是Object类的方法.指锁定当前访问这个对象的线程, 释放对象锁,别的线程可以访问锁定对象。不需要捕获异常, 需要配合 notify()或者notifyAll ()叫醒一个wait在当前对象的线程.只能在同步控制方法中使用。
3. 简单说明线程锁以及如何解决线程同步问题.
synchronized表示的就是锁。当一个方法上有synchronized时就表示这个方法在被一个线程执行时被锁上了,此时若其他线程也来执行这个方法,那么它看见这个方法被“上锁”了,自己就进不去了。只有当那个在执行这个方法线程“办完了事情”之后把锁打开自己出来后在等待的线程才可以进入这个方法。
4. 线程的生命周期及各种状态(明确线程的状态转换)
生命周期: 新建、就绪、运行、阻塞、死亡。
1 新建, 用new语句创建的线程对象处于新建状态,此时它和其他java对象一样,仅被分配了内存。
2就绪, 当一个线程对象创建后,其他线程调用它的start()方法,该线程就进入就绪状态。处于这个状态的线程位于Java虚拟机的可运行池中,等待cpu的使用权。
3 运行, 处于这个状态的线程占用CPU,执行程序代码。在并发运行环境中,如果计算机只有一个CPU,那么任何时刻只会有一个线程处于这个状态。
只有处于就绪状态的线程才有机会转到运行状态。
4 阻塞状态, 阻塞状态是指线程因为某些原因放弃CPU,暂时停止运行。当线程处于阻塞状态时,Java虚拟机不会给线程分配CPU,直到线程重新进入就绪状态,它才会有机会获得运行状态。
5 死亡状态, 当线程执行完run()方法中的代码,或者遇到了未捕获的异常,就会退出run()方法,此时就进入死亡状态,该线程结束生命周期。
1. TCP UDP协议
TCP(transmission control protocol) 是专门设计用于在不可靠的因特网上提供可靠的、端到端的字节流通信的协议。面向连接的协议。TCP连接时字节流而非报文流
UDP(user data protocol) UDP向应用程序提供了一个发送封装的原始IP数据报的方法、并且发送时无需建立连接。是一种不可靠的连接。
2. Socket
TCP Socket通信模型
例子:
TCP:
Server:ServerSocket s = new ServerSocket(6666);
Client:Socket s = new Socket("127.0.0.1", 6666);
UDP:无server和client概念
Socket: DatagramSocket
接收包:DatagramPacket