Java疯狂讲义
第一章 Java语言概述与开发环境
一、java程序的运行机制
1.语言的分类
编译型语言:如C++等,在特定的操作系统上编译为机器语言,执行效率高,但是通常无法在系统间移植,需要重新修改并编译。
解释型语言:如ruby、Python,用专用的解释器对源程序逐行解释成特定平台的机器码并立即执行,不是编译生成可执行文件,而是每次运行,都需要重新解释一遍,直接运行。执行效率低,但是具有跨平台特性。
混合型语言:java是先编译成与系统无关的字节码,即*.class文件,再由解释器来解释执行,即java虚拟机(java virtual machine),class文件只需要面向jvm,不同操作系统的jvm不同,但是接口相同,jvm相当于一种转换器,jvm是java实现跨平台的原因。
2.Java基础知识
JDK(java development kit)提供编译运行java程序所需的各种工具和资源,包括java编译器,java运行环境(JRE,java runtime environment,包含jvm和其他环境支持。),以及java类库。
安装目录下的文件夹
Bin:存放jdk的各种工具命令,常用的javac、java命令就是在该路径下。
Lib:存放了bin目录下命令的实际执行程序。
Src.zip:核心类库的源代码。
设置环境变量,将bin目录的路径添加环境变量,这样系统就可以找到javac和java等命令,来编译生成字节码、解释运行字节码。
3.编译运行helloworld程序
添加环境变量后,系统可以找到编译命令javac,所以在命令行窗口输入
编译
Javac –d desdir srcfile 可以用.号代替desdir,表示当前路径 , java文件中定义了多少个个,就生成多少个class文件。
运行
Java helloworld //java 是运行命令(类名称)
4.CLASSPATH设置环境变量和定位类
1.4版本以前的jdk需要设置环境变量CLASSPATH用来指定运行java程序时,查找class文件的路径,用.表示当前路径,并添加“安装目录\lib\dt.jar”和“安装目录\lib\tools.jar”两个目录路径,指定加载java类。
1.5版本后,不需要添加CLASSPATH环境变量,和dt.jar、tools.jar的路径。如果添加了,则按照添加的路径搜索。
也可以用–classpath命令参数临时指定搜索路径,会严格按照指定路径搜索,不会在当前路径下搜索。CLASSPATH环境变量设置的路径临时无效。
Java –classpath dir1;dir2;…….dirN 执行的java类名
5.java程序的基本规则
纯面向对象,所有的东西必须放在类里,空类编译可以,运行时找不到入口函数报错,入口函数的格式是不可变的。Java程序有很多个类,只要有一个类有入口函数即可。
public class helloworld
{
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}
6.Java源文件命名规则
Java源文件中只可以有一个public类,且源文件的名称必须与该类名相同,可以有多个类,可以没有public类,此时文件名随便定义。
7.常见问题
设置CLASSPATH环境变量,没有加点,不能搜索当前路径;java大小写是区分的;java的安装路径不要包含空格;
8.垃圾回收机制
当一个对象不再被引用时,JRE会有一个后台线程来检测和回收对象,并整理内存碎片,解决了内存泄漏的问题,但是增大了开销,影响性能,且回收算法不能100%搜集所有内存。将对象的引用设置为null,即表示可以回收该对象。回收机制能标记活着的对象,能定位对象之间的引用关系。
第二章理解面向对象
面向对象的编程粒度比面向过程大,java不支持多继承。面向对象软件开发需要经过单个过程:OOA(面向对象分析,对目标系统进行分析,建立分析模型,文档化),OOD(面向对象设计,将文档进行细化,得出设计模式。),OOP(面向对象编程)。
1.UML(universal model language)对程序进行建模
用例图:描述系统的功能,以椭圆表示用例,人形表示角色。
类图:显示系统的静态结构,包括类名,类属性,类方法;以及类之间的关系。
类之间有三种关系
关联关系:一条实线表示双向关联,一条箭头表示单向关联,实心箭头表示组合关系,空心箭头表示聚合关系,聚合关系的实体可以同时是另外一个实体的一部分,比如学生可以篮球协会的会员,同时也是 协会的会员;组合关系的不可以,比如一个人的老婆不可以同时是另外一个人的老婆。
泛化关系:即继承关系,用一个空心箭头表示。
依赖关系:改动一个类,需要被动的改动另外一个类。用虚线箭头表示。
组件图:组件相当于一个功能模块,包括组件名称、接口、和port等图元,组件图显示系统中组件的依赖关系。
部署图:用于描述软件系统如何部署到硬件环境中,系统的不同组件之间的分布地理位置、通讯方式、依赖关系。
顺序图:用于描述各个用例之间的交互信息、交互关系和交互顺序,时间顺序是从上往下的,交互对象的顺序是水平方向箭头指定的顺序。
Java不允许直接访问对象,而是通过对象的引用来操作对象。Java类之间有两种关系:一般特殊关系,例如水果与苹果;整体与部分关系,例如身体和手臂的关系。
第三章数据类型和运算符
Java是一个强类型的语言,变量需先声明后使用,数值类型之间可以自动或强制类型转换。
1.文档注释
Java的文档注释是对java基础类的一个说明,包括类的功能介绍,使用方法,可在官方网站下载。打开index.html即可查看目录。可以在自定义的类中添加文档注释,用javadoc命令生成文档,Javadoc只处理源文件在类、接口、方法、成员变量、构造器和内部类之前的注释,忽略其他地方的文档注释,只处理public和protect标记的类、接口、方法、成员变量、构造器和内部类。加上参数-private,可以提取私有的。开始/**,结束*/。
格式:javadoc 参数 java源文件或者包
支持*.Java,表示所有的java文件,
参数包括三种
-private 提取私有的文档注释
-d<路径> 指定生成的API文档路径
-windowtitle<一个字符串,指定API文档的浏览器窗口标题>
-doctitle<字符串,指定概述页面的标题>
在文档注释中用@加上一些变量名称,指定咋文档中生成对应的选项。
@author 作者
@version 版本
@deprecated 不推荐使用的方法
@param 方法参数说明信息,
@return 返回值说明信息
@see 参考内容
@抛出异常的类容
使用@author 作者 @version 版本两个是需要在javadoc命令中加入 –author 和-version 两个命令参数,其他的不用。
2.标识符和关键字
Java可以跨越多行书写,一个字符串或变量名不能跨多行书写。
Java的变量名称,可以是中文字符日文字符美元符号。
Java所有的 关键字都是小写,例如false;
用超出int范围的值给long变量赋值时,数值后面加上l或L表示long数据,否则会出错。
二进制0B或0b开头,八进制0开头,十六进制以0x或0X开头,负数以补码的形式保存在程序中,补码是源码取反加一。
Java底层保存的字符的编号是0~65535之间的数字,所以可以可以直接计算。
3.基本数据类型
char两个字节,字符类型String用双引号表示,反斜杠需要用转义字符\\。float只能表示8位小数,默认浮点数为double类型,若想表示float值,则后面加上f或F,512表示成指数形式为5.12E2。
java提供三个特殊的浮点值:正无穷大(POAITIVE_INFINITY,正浮点数除以0)、负无穷大(NEGATIVE_INFINITY,负浮点数除以0),非值(NaN,0.0/0.0或者0/0.0或者0.0/0,或者对一个负数开方,0/0出现异常。),NaN不与任何值相等,与NaN自己都不相等。正数除以0会出现异常。用下划线分隔数字,清楚的看出是多少位。
Java的boolean是一种特殊的数据类型,只要一位保存,但由于计算机最小分配单元是字节,所以实际是占1字节,它的取值可以是true或false。它与其他数据类型之间不能相互赋值。String str=true+“”;str会变成“true”;数值型变量也可+“”变为字符串。字符串不能直接转化为基本类型,需要包装类integer.parseInt(“54”);
System.out.println(‘a’+7+”hello”);输出结果为104hello
4.直接量
Null直接量可以直接赋值给String或者引用类型的变量。
第一次使用string直接量时,java类中会有一个常量池保存,后续再使用该字符串直接量时,使用常量池中的直接量。常量池指在编译期间,保存.class中的数据包括类接口、方法中的常量,和字符串直接量。String s2=”hel”+”lo”;String s1=”hello”;s1和s2都是常量池中hello的引用。
Java支持连续复制,但可读性不强,不建议。
取反位运算符包括符号位一起取反,负数的取反是对补码的取反,取反之后变为正数。-5取反之后是4。
左移用0补齐后面空白,右移用符号位补齐空白,无符号右移>>>是用0补齐左边的空白。
位运算时,byte,char,short自动转化为int,为32位,移动位数a需要对32取余后运算。Long是对64取余。
逻辑运算符&和|具有不短路的功能,即第一个为false时继续执行第二个,^两个操作数不同时返回true。
第四章流程控制与数组
1.流程控制
Java7的switch语句可以是java.lang.String类型的变量和表达式,不能是stringBuffer或StringBuilder。
2.数组
定义数组格式建议用type[] arrayname;不建议采用type arrayname[];把type[]看成是一种类型。数组静态初始化:程序员指定初始值,系统决定数组长度;
Array=new type[] {元素1,元素2…..};
Jianhua简化的初始化type[] Array= {元素1,元素2…..};定义的同时初始化。
动态初始化:程序员指定数组长度,系统分配初始值。
type[] Arrayname=new type[10]; 默认初始值整数为0,浮点数为0.0,字符为‘\u0000’,boolean为false,引用为null。
不要同时指定长度又赋值初始化。
数组有length属性,获取数组长度。int[] prices=new int[5]; prices.length
Foreach循环语句
book相当于一个临时变量,循环会把books中的元素依次赋值给book变量,所以不能通过修改book的值来修改books数组中的元素。
public class helloworld
{
public static void main(String[] args)
{
String[] books={"qqqqq","sssss","aaaaaa"};
for(String book:books)
{
System.out.println(book);
book="wwwwwwww";
}
System.out.println('\n');
for(String book:books)
{
System.out.println(book);
}
}
}
3.深入数组
当一个方法执行时,会建立自己的内存栈,方法内定义的局部变量保存在内存栈中,数组的引用保存在栈内存中,数组的值保存在堆内存中。方法执行完后,栈中局部变量会销毁,但是堆中的变量只有当它不被任何引用变量引用时才会被销毁。
二维数组
Type[][] arrname;arrname=new type[10][]; type[0]=new type[4];将二维数组看成一维数组的定义,数组元素类型是type[]。
Type[][] arrayname=type[3[4];
Strign[][] str=new stirng[][]{new string[3],new string[] {“hello”,”world”}};
4.Arrays类操作函数
int binarySearh(type[] a,type key);二分法查找key值的元素位置
int binarySearh(type[] a,int fromindex,int toindex,type key);二分法查找key值的元素位置
type[] copyOf(type[] orginal,int length);复制original数组中的元素为到新数组
type[] copyOfRanger(type[] orginal,int from ,int to);复制original数组中的元素为到新数组
Boolean equals(type[] a , type[] b);判断数组a,b长度和值是否相等。
Void fill(type[] a,type val );赋值给数组val。
Void fill(type[] a,int from, int to );赋值给数组val。
Void sort(type[] a);对数组进行排序。
Void sort(type[] a,int from, int to );赋值给数组val。
String toString(type[] a);
第五章面向对象
1.java的静态方法
Static修饰的方法属于类,用类直接来调用该方法,不能调用类中的其它非静态函数,因为无法确定调用的是哪个对象的方法。不同的对象去调用静态方法,得到相同的结果,因为底层依然是用所属的类去调用。
This默认代表对象本身,当方法中有与成员变量同名的局部变量时,需要在成员变量前加this以区分。同一个类中,一个方法调用另一个方法,被调用者是普通方法,默认使用this作为调用者,如果方法是静态方法,默认使用类作为调用者。
Java中方法不能独立定义,独立执行,要么属于类,要么属于对象。
2.java的参数传递
方法的基本类型的参数传递是值传递,方法中对参数的操作不影响实参的值。引用类型的参数传递也是值传递,实参将引用值赋值给形参变量,但是引用指向同一块堆内存,并没有赋值堆内存中的值,修改形参变量引用指向的变量值,会同时修改实参引用指向的值。
Func(int df,String… arraystring)Sting后面的三个点表示可以传入多个String类型的实参,arraystring作为一个数组接收多个参数值。调用是Func(2,“sfsa”,“dsff”);只能是最后一个参数才能这样。也可以用数组实参去赋值给这个可变形参,例如:FunC(2,new String[] {“sfsa”,“dsff“})
方法重载遇到可变形参时,test(String str); test(String… str);只有参数个数为1个时才会调用test(String str);当参数个数为0或2个以上时会调用test(String… str);用数组形式实参test(new String[] {“aa”});一个参数也会调用test(String… str);
第八章集合
HashSet |
无序,不重复,hashcode()和equals()相等,线程不安全 |
LinkedHashSet |
插入顺序排序,不重复,以链表,线程不安全 |
TreeSet |
有序,不重复,排序通过CompareTo和equals()相等,线程不安全 |
EnumSet |
有序,以枚举值在枚举类中的定义顺序为顺序。线程不安全 |
Arraylist |
插入顺序,可重复,按照索引存储值,线程不安全 |
Vector |
线程安全 |
Stack(栈), |
后进先出,线程安全 |
arraydeque |
Deque是一个双端队列,两头操作。 |
|
|
8.3.Set集合
8.3.1HashSet
无序,不重复,存取查找性能好,非线程同步,集合元素可以是null,判断相同元素的标准是hashcode()方法返回值相等且equals()返回值也相等。Hashcode不同,equals相同,会存在不同位置。hashcode()方法计算存储位置,快速存取;比数组,长度可变,内存可不连续。改变元素的值容易引起混乱。Add,remove;相同元素多次插入HashSet时,会以链表的形式存储在相同位置,称为hash桶,会影响性能。
8.3.2LinkedHashSet
根据插入顺序排序,不重复,以链表维护元素的次序,先插入在前。性能低于hashset。
8.3.3TreeSet
有序,不重复,排序通过CompareTo(Object obj)方法,CompareTo相同的无法添加。定义类需要实现Comparable接口。保存相同类型的对象。存储规则:equals和CompareTo返回结果同步。修改元素会引起混乱。last(),first(),lower()等。自然排序按升序排列,定制排序在构造函数中传入Comaprator接口lambda表达式。
TreeSet是有序,通过插入对象的CompareTo方法比较,返回为0表示相同,则无法在添加,自定义类需要实现该方法。TreeSet中应该添加同一个类的对象。
Equals和CompareTo返回的结果要一致,否则会出错。
修改TreeSet里的实例变量会导致不在有序,且可能出现重复值,删除重复的对象会失败,可以删除没有没修改过或不与修改过的对象相同的对象。所以尽量不要修改TreeSet和hassSet的对象。
自然排序:TreeSet自动调用集合元素的CompareTo方法来比较元素之间的大小关系,进行升序排列。
定制排序,创建TreeSet对象时,以lambda表达式传入函数式接口Comparator,实现compare函数,用于比较。还是根据返回值判断大小。对象自身的CompareTo接口就不用了。
专为枚举类设计的集合类,有序,按枚举类中定义的顺序排序,存储紧凑高效。
8.3.4EnumSet类
有序,以枚举值在枚举类中的定义顺序为顺序,不可插入null;
Set都是线程不安全的,hashset性能高于treeset,要求有序时才使用treeset。迭代访问时linkedhashset性能高于hashset;
8.4List集合
8.4.1List接口和ListIterator接口
List是按索引插入值,0开始,可重复,通过对象equals函数判断是否相等。
indexOf(Objrct o);查找object对象第一次出现的索引
sort(Comparator c)根据参数对list排序。
Set只提供iterator()方法,List还有额外的listIterator()方法,返回listIterator对象,有hasPrevious() previous(),add()三个方法。
ListIterator可以通过hasNext正向遍历list,可以通过hasPrevious反向遍历list。
8.4.2ArrayList和Vector实现类
Arraylist和Vector默认大小为10 ,可以用initialCapacity(int)或ensureCapacity(int)方法来设置初始大小,通过trimToSize()将大小设置为容量大小,减少空间占用。
Vector的子类Stack(栈),后进先出,性能差。
ArrayList是线程不安全的,而Vector是线程安全的。
Arrays中有一个aslist(object… a)将一个数组或者指定个数的对象转换成list集合,格式固定,不可增加或删除。
List实例
import java.util.*;
public class helloworld
{
public static void main(String[] args)
{
List booklist=new ArrayList();
booklist.add(new String("疯狂java讲义1"));
booklist.add(new String("疯狂java讲义2"));
booklist.add(new String("疯狂java讲义3"));
ListIterator lit=booklist.listIterator();
while(lit.hasNext())
{
System.out.println(lit.next());
lit.add(new String("-----------分隔符----------"));
}
System.out.println("开始反向");
while(lit.hasPrevious())
{
System.out.println(lit.previous());
}
}
}
8.5Queue集合
Queue队列,先进先出,插入队尾,对头取出。
8.5.1PriorityQueue实现类
PriorityQueue实现类,并不是先进先出,而是进行排序,小的在头,大的在尾,不能是null,需要相同对象。排序分自然排序很定制排序,定制排序需在构造器中传入实现Comparable接口。
8.5.2deque接口和arraydeque实现类
Deque是一个双端队列,两头操作。XXXFirst() XXXLast()操作函数。
ArrayDeque是接口Deque的实现类,
8.5.3 Linkedlist实现类
可以当做list、stack和deque来使用,内部采用链表实现,随机访问性能较差,插入删除性能较好。
遍历集合元素,ArrayList和Vector采用get方法,linkedlist采用itertor。
8.6 Map集合
Hashmap
线程不安全能使用null作为key或者value;hashtable线程安全,不能使用null作为key或者value,equals判断键值是否相等。 如果采用可变对象作为hashmap的键值,程序修改了对象,导致map无法正常访问修改的键值。
Linkedhashmap
按插入顺序保存键值对。
TreeMap
有序,是红黑树结构,每个节点是一个key-value对,根据key值进行排序,有自然排序和定制排序。
Properties
方便的操作属性文件,,文件内容格式属性名=属性值,load加载,store保存,setProperty()设置,getProperty()获取值。
WeakHashMap
保留对对象的弱引用,一旦系统垃圾回收后,则map里的对象会被删除,wmap.Put(“java”,“new String(中等));java是直接量是强引用,不会删除。wmap.Put(new Stirng(“C++”),“new String(中等));C++为弱引用,回收会被删除。
IdentyHashMap
与hashmap类似,只是采用==来判断key值是否相等。而不是equels和CompareTo对比。允许使用null作为key和value。
EnumMap
创建时必须指定枚举类,将枚举值与对应的关联值对应起来,以枚举值作为key值,根据枚举值的顺序排列,不允许null作为key值,可以作为value值。
8.8操作结合的工具类Collection
8.8.1集合的操作
void reverse(List list),反序
void shuffle(List list),随机排序,打乱排序
void sort(List list)自然顺序排序
void swap(List list,int i,int j)调换list中的两个恶元素
void rotate(List list,int distence)根据distence的值将list中的元素循环移位。
Int binarySearch(List list , Object key)list必须有序,快速查找键值的索引。
Int frequency(collection c,Object o)查找集合中出现的次数。
Boolean replaceAll(List list, Object oldVal,Object newVal)新值代替所有旧值。
8.8.2集合同步封装Collection.synchronizedXxx
List list=Collection.synchronizedList(new ArrayList());
8.8.3集合的只读设置
通过Collection的emptyXxx()方法创建空的只读集合,使用singletonXxx()创建只含有一个对象的只读集合,通过unmodifiableXxx()创建只读集合。
第九章泛型
使集合能够识别保存的类型 List<String> strlist=new ArrayList<String>();java7后红色String可省略。泛型的实质是允许在定义接口、类时声明类型形参,创建对象时传入类型实参,类似C++的模板。Public class Appple<T>, 泛型解决集合不确定保存什么类型的对象问题,解决了雷和接口不确定采用什么类型的参数问题。
9.2泛型类、接口定义和继承
从泛型类派生子类或泛型接口实现类,需要泛型的实参。Public calss A extends Apple<String>。不传入实参,则泛型当做Object处理。泛型形参不同,但是不是不同的类,静态中不允许使用泛型。List<String>不是List<Object>的子类,不能进行传递。
9.3类型通配符
List<String>不能当做实参传递给List<Object>,需要定义List<?>类型通配符。test(List<?> c), List<?>表示各种泛型List的父类,但是只能作为泛型形参,不能创建对象保存数据。Test(List<? extends fruit>); extends fruit表示只有fruit的子类才可以单做形参传入,因为无法确定List保存的到底是哪个子类对象,所以不能执行add操作。定义泛型类时,也可以限制,例如public class Apple<T extends Number>表示只有number的子类才可以传入。多个限制用&号连接public class Apple<T extends Number & String>。类限必须在前,接口限制在后。
9.4泛型方法
为了解决使用通配符时,不能进行写操作,只能进行读操作,java提供泛型方法。
Static <T> void addArrayToCollection(T[] a, Collection<T> c)
{
For(T o:a){c.add(o);}
}
static <T> void test(Collection<? externs T> from, Collection< T> to)
自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取: