第一章,JAVA技术体系架构
JAVASE,(标准版),核心技术。小型桌面应用。
JAVAME,(微型版),嵌入式,电子产品程序。
JAVAEE,(企业版),web应用。涉及的技术面很广。
计算机语言机制
编译型和解释型。
编译型,一篇文章,整个翻译,再看。
解释演讲,旁边站着翻译,说一句,翻译一句。
java属于解释型(编译型和解释型)
JDK:Java程序的开发环境(开发工具包)包含JRE(Java运行时环境)和Java开发工具,Java基础类库。
JRE:Java程序的运行时环境包含JVM(Java虚拟机),Java API,Java核心类库等
JVM:Java虚拟机,保证Java的跨平台性,把字节码解释为平台上的机器指令执行。
程序源代码(Fn.java)——>编译器——>字节码(FN.class)———>JAM(java虚拟机)———>机器码———>计算机
JAVA API 文档:JAVA程序开发用的编程词典。
面向对象 ,分布性,可移植性,解释性,安全性,健壮性,多线程性,高性能,动态。
文件名必须与类名同名,JAVA是区分大小写的,基本组成单元是类(属性+方法),含有main()方法的类称之为主类。
变量:在程序运行过程中,空间内的值是变化的,这个内存空间称为变量,内存空间名称为变量名。
字符集:ASCll字符集(美国信息互换标准编码),GB2312字符集(中国国家标准的简体中字字符集),Unicode字符集(utf-8,utf-16,utf-32),JAVA语言中基本所有的输入元素都是采用ASCll,而标识符,字符,字符串和注解则采用Unicode。
分隔符:分为空白符和普通分隔符,任意两个相邻的标识符之间至少有一个分隔符。
标识符:变量,常量,方法,对象和类等的名字作为标识,java中的标识符的命名规则:可以包含数字,但不能以数字开头,除下划线和$,不能包含其他特殊字符,如空格,区分字母大小写,不能使用JAVA关键字。
变量和常量:语法 , (final)数据类型 变量名 =初始值;常量习惯采用全部大写字母,在定义时,需要对常量进行初始化,初始化后,在应用程序中就无法在对该常量赋值,
变量的作用域:变量可分为局部变量(定义在某个程序块(程序块就是用{}包含的代码块)内或方法体内)和成员变量,当申明的语句执行时,会在内存中该变量分配存储空间,当超过变量作用域的范围后,系统会释放他的值,即变量的生存期受到其作用域的限制,如果在作用域中初始化一个变量,则每次调运该代码块时系统都会从新初始化该变量。
局部变量:在使用之前必须进行初始化,即变量必须有值后才能被使用。在互不嵌套的区域可以定义同名同类型的局部变量。
成员变量:是存放在堆中,局部变量是存放在栈中。
数据类型:引用类型(指向存储在内存的“堆”中数据的指针或引用(地址)包括类,接口,数组和字符串,运行时动态分配内存,存取速度慢)+基本类型(表示一个具体的数字,字符,布尔值,基本类型存放在内存的“栈”中,可以快速从栈中访问数据)
基本类型
类型名称 | 关键字 | 大小 | 取值范围 |
字节型 | byte | 8位 | -2^7~~2^7-1 |
短整型 | short | 16位 | -2^15~~2^15-1 |
整型 | int | 32位 | -2^31~~2^31-1 |
长整型 | long | 64位 | -2^63~~2^63-1 |
浮点型 | float | 32位 | 3.4e—38~~3.4e+38 |
双精度 | double | 64位 | 1.7e—38~~1.7+38 |
布尔型 | Boolean | 1位 | true/false |
字符型 | char | 16位 | “\u0000”~"\uFFFF" |
字符型
Java语言中字符型char是采用16位的Unioode字符集作为编码方式,char通常用于表示单个的字符,字符值必须使用‘()。字符值有以下三种表示方式,单个字符,转义字符,使用Unicode值来表示。
\b | 退格符() | \u0008 |
\t | 制表符 | \u0009 |
\n | 换行符 | \u000a |
\r | 回车符 | \u000d |
\'' | 双引号 | \u0022 |
\' | 单引号 | \u0027 |
\\ | 反斜杠 | \u005c |
引用类型
引用类型变量中的的值是指向内存“堆”中的指针,即该变量的值是存储在堆中的。基本类型变量和引用类型变量名是存储在栈中的。
Java语言中通常有5种引用类型:
数组:(具有相同数据类型的变量的集合),
类(class):(变量和方法的集合)
接口(inteface):一系列方法的声明,方法特征的集合,
枚举(enum):一种独特的值类型,用于声明一组命名的常数。
空类型(null type):空引用,即值为null的类型,空类型没有名称,不能声明一个null类型的变量,null是空类型的唯一值。
空引用(null)只能被转换成引用类型,不能转换成基本类型,不要把一个null赋值给基本数据类型的变量。
类型转换(自动类型转换+强制类型转换):
强制类型转换:数据类型 变量1=(数据类型)变量2;
可以将任何类型的数据转换为String类型。
二进制码中零为正,一为负,负数一般以补码形式表示,即以个负数先求其正数的二进制码,取反,加一,得到的为补码,求其二进制反向。
运算符由高到底的顺序为;增量减量运算符>算数运算符>比较运算符>逻辑运算符>赋值运算符>
一元运算符:++,--,~,!;(增量减量运算符的优先级>算数运算优先级)
位运算符:~,&,|,^,>>,<<,>>>;(&按位与:同一为一,否者为零。|按位或同零为零,否则为一。按位取反,变换。^按位异或,二进制同为零,异为一。位移操作(>>右移左补高位,左移<<右补零,无符号右移>>>填零))
位移运算符适合的数据类型有byte,short,char,int和long;位移可以实现整除(乘)以2^n的效果,一个数左移n位,即乘以2^n一个数右移n位,即除以2^n;
逻辑运算符:!,&&,||;(在逻辑表达式中从左端的表达式可推断出整了表达式的值称为短路(&&),始终执行逻辑运算符的两边的表达式称为非短路(&))
三元运算符“? :”
算数运算符:+,-,*,/,%;
运算符:>,>=,<,<=,++,!=;
编译器报错illegal character时意识是非法字符。编码中可读性第一,效率第二。
复合语句
1.java语言中复合语句是整个块区为单位的语句,所以又被称为块语句。复合语句为局部变量创建一个作用域,
2.if语句中若没有语句序列,可以用"{}"或者";".
3.switch多分支语句,switch(整形,字符型,字符串类型),case“整数,字符型,字符串型”
4.break跳出循环体,continue跳出本次循环。
数组:
一维数组:数据类型 []数组名=new 数据类型[大小]
求数组长度:数组名.length;
当数组使用new分配存储空间后,数组中的元素会具有默认初始值,
- 数值型的初始值为0;
- 布尔型的初始值为false;
- 字符型的为‘\0’(字符串结束标识);
- 引用类型的则为NULL(空引用)字符串String就属于引用类型;
数组变量名存放在栈里,而数组中的元素存放在堆里;
数组名中存放的数据是数组的首地址,系统为数组分配的存储空间时连续的,指定长度的且大小固定不变,
初始化数组(静态+动态):
静态初始化:在定义数组的同时就对该数组进行初始化 ,静态初始化时不指定数组的大小。即[]不可有值。
// 静态初始化
Object[] object = {};
Object[][] objects = {{}};
Object[] objects1 = new Object[]{};
动态初始化:将数组的定义和数组的初始化分开。
foreach遍历数组
for(数据类型 变量名:数组名)foreach中的数据类型必须与数组类型一致。
标签:标签名:循环体{break 标签名}跳出指定循环,continue也支持标签功能。
跳出多重循环的方法一是使用标签,二是使用标示。
如果一维数组的各个元素任然是一个数组,那么它就是一个二维数组,
二维数组 数据类型[][]数组名=new 数据类型[大小];
关于数组的基本操作:
java.util包的Arrays类包含了用来操作数组的方法,
1,遍历数组:利用foreach语句。
2,填充替换数组元素:通过Arrays类的静态方法fill()来对数组中的元素进行替换,语法:Arrays.fill(数组名,填充值);选择填充:Arrays.fill(数组名,[,),填充值);
3,对数组进行升序排序:Arrays.sort(数组名);
java.util.Scanner类创建一个从键盘接受数据的扫描器,
System.in代指键盘,与System.out指带显示器,
使用Scanner类的nextInt()可以从键盘接受一个整数,System.exit(0)退出整个应用程序。
第三章:面向对象基础(Object Oriented)
一,面向对象简介
1 ,面向对象思想:使系统能够直接反应问题,并保持事物及其相互关系的本来面目。面向对象,在基于对象的基础上增加了多态性。所谓多态,就是可以用统一的方法对不同的对象进行同样的操作
2 ,从世界观的角度:面向对象的基本哲学是认为世界是由各种各样具有自己的运动规律和内部状态的对象所组成的,不同的对象之间的相互作用和通信构成了完整的现实世界。按照世界的本来样子去理解世界,通过对象及其相互联系反映世界。
3 ,从方法学的角度:面向对象的方法是面向对象的世界观在开发过程的直接利用。面向对象强调系统的结构应该直接与现实世界的结构相对应。围绕现实世界中的对象来构造系统,而不是围绕功能来构造系统。
4 ,面向对象分析(OOA):确定需求或者业务的角度,按照面向对象的思想分析业务。
5 ,面向对象设计(OOD):是一个中间过度环节,在OOA的基础上建立所要操作的对象以及相互之间的联系,被OOP接受。
6 ,面向对象编程(OOP):根据真实的对象来构建应用程序模型。
二,面向对象名词(对象,类,类的关系,消息,方法)
1,对象:一切事物皆对象,具体的事物,抽象的规则,计划或事件等,对象将属性与行为封装。
2,类:具有相同或相似性质的对象的抽象,对象的抽象就是类,类的实例化就是对象,类=特征(对象属性(状态)的抽象,即变量)+行为(对象操作的抽象,即方法),对象的属性提供数据,方法则对数据进行相应的操作。类是一个模板,指明范围,对象是类的实例化(具体事物),
3,类的关系:继承关系(一般到具体),关联关系(整体到部分)。
4,消息和方法:消息能够使对象之间进行通信,方法是类的行为实现,一个方法有方法名,参数方法体。
三,面向对象特征
1,唯一性:每个对象都是唯一的,自身具有唯一的标识。
2,分类性:将具有一致属性和行为的的对象抽象成类。
3,继承性:子类自动继承父类的属性和方法,在软件开发中,类的继承性使所建立的软件具有开放性,可扩充性,通过类的继承关系,使公共的特性能够共享,提高代码的可重用性,减少冗余。
4,多态性:指相同的操作,过程可作用于多种类型的对象上并获得不同结果。不同对象,收到同一消息可以产生不同的结果,即具有不同的行为表现。称为多态性。编译时类型和运行时类型不一样。
5,抽象类和接口:多态的实现并不依赖具体的类,而是依赖于抽象类和接口。父类通常会被定义为抽象类,抽象类不能实例化对象,
四,类的声明:
具有相同属性和共同行为的的一组对象的集合。
类的声明就定义了一个类,语法格式;[访问符] [修饰符] class 类名{[属性][方法]}
- 访问符用于指明类,属性或方法的访问权限,public(公有),protected(受保护的),private(私有的)或默认
- 修饰符用于指明所定义类的特性,可以是abstract(抽象),static(静态),final(最终)
- 类名命名与变量名一样必须符合命名规范,一个或者多个有意义的单词连续,首字母大写
- 含有main()方法的类被称为主类。
- 属性:数据值,方法:函数
类中的变量被称为实例变量或成员变量,定义在类中的方法或者 属性被称为为类的成员。
五,对象的创建和使用
1 ,创建对象语法: 类名 对象名 =new 类名();
2 ,使用一个new关键字创建一个类的对象,new关键字为对象动态分配内存空间,并返回它的一个引用且将它内存初始化为默认值。定义一个类的对象,此时栈上会分配空间,存储对象在堆中的地址(即对象的引用);然后利用new关键字在堆中为该对象分配空间。所有类的对象都是动态分配空间。
3 ,如果不想给对象分配空间,可以使用null关键字给对象赋值,例:类名 对象名=null;标识一个不确定的对象,对象引用为空,可以将null赋值给引用型变量,但不可以赋值给标准型变量。
4 ,在Java中,当某一个非null的引用类型变量指向的对象不再使用时,可以让其指向null;则该对象将不被使用,并由JVM垃圾回收机制去回收。
5,对象的使用:访问对象属性(对象名.属性名),调用对象的方法(对象名.方法名())。
Java语言中的修饰符权限
访问包位置 | 类修饰符 | ||
private(私有) | protected(受保护) | public(公有) | |
本类 | 可见 | 可见 | 可见 |
同包其他类或子类 | 不可见 | 可见 | 可见 |
其他包的类或子类 | 不可见 | 不可见 | 可见 |
六,方法(类的行为的体现)
1,语法:[访问符] [修饰符] 返回类型 方法名([参数列表]){//方法体}。方法体中局部变量不可定义为static。方法可以初始化。
2,方法的参数传递机制:分为值传递和引用传递。形参必须要写数据类型。
(1)值传递:实参和形参在内存中占不同的空间,即在传递过程中,形参要分配空间。即形参值的改变不会影响原来的实参。
(2)引用传递:将实参的地址传递给形参,被调方法通过传递的地址,获取其指向的内存空间,即在原来内存空间直接操作。
Java程序总是从main()函数开始执行的,
3,构造方法:也称构造函数,是类的一个特殊方法,创建对象初始化对象中的属性值,一般创建对象时,对象中的数据都被初始化为默认值(数值为0,引用为null),语法:[访问符] 类名 ([参数列表]){初始化语句},构造方法的方法名必须与类名一致,没有返回类型。可以定义一个空的构造方法
4,this关键字:代表当前所在类将来产生的对象,即将来用该类new出来的对象,用于获取当前类的对象的引用,解决当前变量命名冲突(方法中的局部变量与类的属性同名时),利用this。属性名访问类的属性。在初始化对象时 [类名]对象名=new [类名](属性值),
5,默认构造方法:类名 对象名=new 类名(),无参构造方法,Java中允许定义多个构造方法,属于构造方法重载。
6,方法重载:同一个类中包含两个或者两个以上的方法名相同,但参数列表不同,称为方法重载,原则:同类,同名,参数列表不同,不能将返回值类型的不同当成两个方法的区别。
7,可变参数:即允许参数定义方法时参数的个数是可变化的。语法:[访问符][修饰符]<返回类型> 方法名([参数表列],数据类型...变量){//方法体 }}参数b是一个可变参数,该参数可以接受多个参数值,多个参数值被当做数组传入。可变参数只能处于列表最后,一个方法最多只能包含一个可变参数,可以传入多的参数,也可以传入一个数组。
七,封装和访问控制:
1,包:提供了类的多层命名空间,解决类的命名冲突,类文件管理。定义包:package 包名;使用package关键字可以指定类所属的包,在物理上,java使用文件夹目录来组织包,包中的类以及编译后的字节码都存放在包名的目录中。定义包需要注意一下几点:
- package语句必须作为java源文件的第一条非注释语句
- 一个 JAVA源文件只能有一个包,即只有一条package语句,不能有多条package语句,
- 定义包之后,java源文件中可以定义多个类,这些类将全部位于该包下。
- 包的一般命名方法:公司域名反写.项目名.模块名。的形式创建不同的子包。
2,导入包:java语句中若要访问其他包中的类,则可以使用import语句导入。
1。语法:import 包名.*,*仅代表类名或者impotr 包名.类名,导入包之后可以直接访问包中的类,也可以利用在类名前直接添加完整的包名即可(解决异包同类名的问题)
2。一个Java源文件可以有多条import语句,但只能有一条package语句,且在最前。但可以有多条import语句。
3,访问控制符:Java提供了4个访问控制符,private(私有),protected(受保护的)和public(公有的),还有一种不见任何访问控制符的默认访问级别friendly(友好),
- private(当前类访问权限):被声明为private的成员只能被当前类中的其他成员访问,不能在类外看到。
- friendly(默认,包访问权限):如果一个类或类的成员前没有任何访问控制符,则获得默认friendly访问权限,默认可以被同一包中的所有类访问。
- protected(子类访问权限):被声明为protected的成员可被同一包中的其他类访问,也可以被不同包中的子类访问。
- public(公共访问权限):被声明为public的成员可被同一个包中或不同包的所有类访问,共用与任何类。
- private,protected和public都是关键字,而friendly不是关键字,它只是一种默认方式
4,静态成员:
1。java中可以使用static关键字修饰类的成员变量和方法,称为静态成员。静态成员的限制级别是“类相关”的,可以直接通过类名调用(类名.属性,类名.方法),无需通过声明的实例对象进行访问。与类相关的静态成员称为类方法,类变量,与实例相关的普通成员称为实例变量,实例方法,需要通过声明实例对象来调用(类名.属性,类名.方法);
2。类变量属于整个类,当系统第一次准备使用该类时,系统会为该类的类变量分配内存空间,到类被卸载时,该类的变量所占的内存才被系统的垃圾回收机制回收,通过对象访问类变量只是一种假象。,
3。类的静态变量和静态方法,在内存中只有一份,供所有对象共用,起到全局的作用。在静态方法中不可以使用this关键字,不可以直接调用非静态方法。
4 。可以利用static初始化方法,语法:public class 方法名 { static { 静态区域:初始化语句 } }当代码执行时,首先执行static块中的程序,并且只会执行一次。
5,对象数组
一个数组中所有元素都是对象,语法 类名[] 数组名 =new 类名[长度];因为数组中的每个元素都是对象,所以每个元素都需要实例化,可以利用for循环实现。:数组名[长度]=new 类名([初始化值]);
第四章,核心类
1,基本类型的封装类
1。Java为八个基本数据类型提供了对应的封装类,Byte,Short,Integer,Long,character,Float,Double,Boolean,Java提供了自动装箱和自动拆箱的功能,所以基本类型和封装类之间可以直接赋值。
2。装箱和拆箱:基本类型与其对应封装类之间能够自动进行转换的原因。
3。装箱:将栈中的数据封装成对象存放到堆中,Integer intobj=5;与Integer intobj=new Integer(5);相同
4。拆箱:将封装的对象转换成基本类型数据值。将堆中的数据存放到栈中。
装箱:Integer integer = Integer. valueOf (12);
拆箱:int i = integer.intValue();
基本类型包装类的常用方法
方法 | 返还值 | 功能描述 |
XxxxValue()// 拆箱方法 | Xxxx | byteValue(),booleanValue(),,intValue(),charvalue()以Xxxx的类型返回对象值 |
compareTo(Xxxx anotherInteger) | int | 在数字上比较两个Xxxx对象,int str1(调用对象) = int1.compareTo(int2); 如果这两个值相等,则返回0,如果调用对象的数值小于anotherInteger的数值,则返回正值,反之,返回正值。返回int,自然排序 |
equals(Object IntegerObj) | boolean | 比较此对象与指定的对象是否相等,返回boolean |
intValue() | int | 以 int 型返回此Integer对象 |
shortValue | short | 以 short型返回Integer对象 |
补表
toString() | String | 返回一个表示该Xxxx值得String对象 |
valueOf(String str)// 装箱 | Integer | 返回保存指定的String值得Xxxx对象 |
parseInt(Strung str) | int | 返回包含在由str指定的字符串中的数字的等价整数值 |
将字符串的值转换为基本类型的方法:
- 直接利用封装类的构造方法,即Xxx(String s)例:int num1=new Integer("12");
- 调用封装类提供的int num =Integer.paresXxx("123");
将基本类型的值转换为字符串:
- 直接使用一个空字符串来连接数值即可,String as=" "+as;
- 调用封装类提供的toString()静态方法,String as=Integer.toString( 100);
- 调用String类提供的valueOf()静态方法,String as=String.valueOf(45);
Number类的方法:byteValue(),intValue(),floatValue(),shortValue(),longValue(),doubleValue(),以Xxx的形式返回指定的数值。是其他封装类的父类。
2,Object类
Object对象定义在java.lang包中,是所有类的顶级父类,在java体系中所有类都直接或间接的继承了Object类,因此,任何的java对象都可以调用Object类中的方法,任何类型对象都可以赋值给Object类型的变量。
Object常用方法
方法 | 功能描述 |
protected Object clone() | 创建并返回当前对象的副本,该方法支持对象的复制 |
public booolean equals(Object obj) | 判断指定的对象与传入的对象是否相等 |
protected void finalize() | 垃圾回收器调用此方法来清理即将回收对象的资源 |
public final Class<?>getClass() | 返回当前对象运行时所属的类型 |
public int hashCode() | 返回当前对象的哈希代码值 |
public String toString() | 返回当前对象的字符串表示 |
1.“==”与equals()的区别:“==”表示的是两个对象的地址是否相等,即判断引用的是否是同一个变量,equals()方法通常用于比较两个对象的内容是否相,对象2.equals(对象1),比较对象1与对象2,返回一个Boolean值。
2.toString类的toString()方法返回当前对象的字符串表示,当类没有重写String()方法时,系统会自动调用Object默认的toString()方法,显示的字符串格式将是“类名@哈希代码值”
3,字符串类
声明字符串变量必须经过初始化才能使用。
字符串就是一连串的字符序列,java提供了String,StringBuffer和StringBuilder三个类来封装字符串。三者的区别:
1.String创建的字符串是不可以变的,当使用String创建一个字符串后,该字符串在内存中是一个不可改变的字符序列,如果改变字符串变量的值,其实际是在内存中创建一个新的字符串,字符串变量将引用新创建的字符串地址,而原来的字符串在内存中依然存在且内容不变,直至java的垃圾回收系统销毁。
2.StringBuffer字符缓存区类是一种线性安全的可变字符序列,创建的字符串是可变的,当使用StringBuffer创建一个字符串后,该字符串的内容可以通过append(),insert(),setCharAt()等方法给变,而字符串所引用的地址不变,如果想获取StringBuffer()的内容,可以通过调用toStrong()方法转换为一个String对象。
3.StringBuilder类创建一个可变的字符串,不同的是StringBuffer是线性安全的,而StringBuilder没有线程安全,性能好。
String常用类方法
String() | 创建一个包含0个字符的sreing对象(不是返回空)String s =new String(),当字符不为零时,构造字符串值对象 |
String(char[] value) | 使用一个字符数组构造一个String对象:定义字符数组,String s=new String(字符数组名); |
String(char []a,int offset,int length) | 提取字符数组中offset位置的length长度的字符创建字符串对象:String s=new String(字符数组名,2,4); |
String(StringBuffer/StringBuilder as) | 根据StringBuffer/StringBuilder对象创建对应的String类 |
char charAt(int index) | 获取字符串中index位置(0开始)的字符,char a=字符串名.charAt(2); |
int compareTo(String s) | 比较两个字符串的大小,相等返回零,不相等返回不相等字符编码的差 |
boolean endsWith(String s) | 判断一个字符串是否以指定的字符串结尾:s可以是字符串/字符串名 |
boolean equals(String s) | 比较两个字符串的内容是否相等:s可以是字符串/字符串名 |
byte[] getBytes() | 将字符串转换为 字节数组 |
int length() | 返回字符串的长度 |
int indexOf(String s) | 找出指定的子字符串在字符串中第一次出现的位置,没有返回-1 |
String subString(int beg) | 获取从beg位置开始到结束的子字符串 |
String subString(int beg ,int end ) | 获取从beg位置开始到end位置的子字符串 |
String split(String sign) | 使字符串按照指定的分割字符或字符串对内容进行分割,并将分割后的结果存放在字符数组中 |
String toUpperCase/toLowerCase() | 将字符串转换为大写/小写 |
static String valueOf(X x) | 将基本类型转换为字符串类 |
String replace(char oldChar,char new Char) | 将指定字符(串)替换为新的字符(串),不能用字符替换字符串 |
字符串分割:对于字符串分割,如果想定义多个符号,可以使用‘|’进行区分,也可以使用正则表达式,同时也可以限定拆分次数。;字符串名.split(String sign,int limit)设计到有歧义的符号要用转义字符,转义字符的符号为"\\"与注释相反。
字符串的连接:当字符串与字符串进行“+”连接时,第二个字符串会连接到第一的字符串之后,当字符串与其他类型进行“+”连接时,所有其他类型的数据都将转换成字符串与前面的进行连接,当其他类型与字符串进行“+”连接时,其他类型按照从左到右进行运算。最后在与字符进行连接。
格式化字符串:
常规类型的格式化:
使用正则表达式:
StringBuffer类:
StringBuffer类常用的方法
方法 | 功能描述 |
StringBuffer() | 构造一个不带字符的字符串缓存区,初始容量为16个字符 |
StringBuffer(int capacity) | 构造一个不带字符,但具有指定初始容量的字符串缓存区 |
StringBuffer(String str) | 构造一个字符串缓存区,并将其内容初始化为指定的字符串内容 |
append(String str) | 在字符串末尾追加一个字符串 |
char charAt(int index) | 返回指定下标位置的字符 |
int capacity() | 返回字符缓存区容量 |
StringBuff delete(int start ,int end) | 删除指定开始下标到结束下标之间的子字符串 |
StringBuffer insert(int offset,String str) | 在指定位置插入一个字符串,该方法提供多种方法的重载方法, |
int lastIndexOf(String str) | 返回最后出现指定字符串的下标 |
setCharAt(String str) | 返回指定字符的下标 该方法的作用是修改对象中索引值为index位置的字符为新的字符ch |
setLength(int newLength) | 设置长度 |
int length() | 返回字符串的长度 |
StringBuffer replace(int start,int end,String str) | 在指定的开始下标和结束下标之间内容替换为指定的子字符串 |
StringBuffer reverse() | 反转字符串序列 |
String subString(int beg) | 获取从beg位置开始到结束的子字符串 |
String subString(int brg,int end) | 获取从beg位置开始到end位置的子字符串 |
String toString() | 返回当前缓存区中的字符串 |
StringBuilder字符串生出器类与StringBuffer类似,也是创建可变的字符串序列,只不过没有线程安全控制。
StringBuilder类常用方法
方法 | 功能描述 |
StringBuilder() | 构造一个不带字符的字符串生成器,初始值容量为16个字符 |
StringBuilder(int capacity) | 构造一个不带字符,但具有指定初始容量的字符串生成器 |
StringBilder(String str) | 构造一个字符串生成器,并将其内容初始化为指定的字符串内容 |
append(String str) | 在字符串末尾追加一个字符串 |
char charAt(int index) | 返回指定下标位置的字符 |
int capacity() | 返回字符生成器容量 |
StringBuilder delete(int start,int end) | 删除指定开始下标到结束下标之间的子字符串 |
StringBuilder insert(int offsrt,String str) | 在指定位置插入一个字符串,该方法提供多种参数的重载方法 |
int lastIndexO(String str) | 返回最后出现指定字符串的下标 |
setCharAt(int index, char ch) | 设置指定下标的字符 |
setLength(int newLength) | 设置长度 |
int length() | 返回字符串的长度 |
StringBuilder reverse() | 反转字符串序列 |
StringBuilder replace(int start,int end,String str) | 在指定开始下标和结束下标之间内容替换成指定的字符串 |
String subString(int beg) | 获取从beg位置开始到结束的子字符串 |
String subString(int beg,int end) | 获取从beg位置开始到end位置的子字符串 |
String toString() | 返回当前缓存区中的字符串 |
scanner类
scanner类常用的方法
Scanner(File source) | 构造一个从指定文件进行扫描的Scanner |
Scanner(InputStream ) | 构造一个从指定的输入流进行扫描的Scanner |
Boolean hasNext(Pattern pattern) | 判断输入的数据是否符合指定的正则标准 |
Boolean hasNextInt() | 判断输入的是否是整数 |
Boolean hasNextFloat() | 判断输入的是否是单精度浮点型 |
String next() | 接收键盘输入的内容,并以字符串形式返回 |
String next(Pattern pattern) | 接收键盘输入的内容,并进行正则验证 |
int nextInt() | 接收键盘收入的整数 |
fioat nextFloat() | 接收键盘输入的单精度浮点数 |
Scanner useDelimiter(String pattern) | 设置读取的分隔符,输出带空格的字符串 |
Math类
Math常用类的静态方法
方法 | 功能描述 |
abs(double a) | 求绝对值 |
ceil(double a) | 得到不小于某数的最小整数 |
floor(double a) | 得到不大于某数的最大整数 |
round(double a) | 四舍五入返回int或long型 |
max(double a,double b) | 求两个数中的最大值 |
min(double a,double b) | 求两个数中较小值 |
sin/cos/tan() | 求在正弦/正切/余弦 |
sqrt(double a) | 求平方根 |
pow(double a,double b) | 第一个参数的第二个参数次幂的子a的b次 |
random() | 返回在0.0到1.0之间的数,大于等于0.0小于1.0 |
Data类
date类常用方法
Date() | 默认构造函数,创建一个Data对象并以当前系统时间来初始化该对象 |
Date(long date) | 构造方法,以指定的long初值初始化一个Data对象,该long值是1970年1月1日00:00:00GMT时间以来的毫秒数 |
boolean after(Date when) | 判断日期是否在指定日期之后,是则返回true反之false |
boolean before(Date when) | 判断日期时间是否在指定日期之前,同上 |
int compareTo(Date date) | 与指定日期比较,相等返回0,之前返回<0的数,之后返回>0的数 |
String toString | 将日期转换为字符串,字符串格式为(dow mon dd hh:mm:ss zzz yyyy)其中dow 是一周中的某一天(Sun,Tue,Wed,Thu,Fri,Sat) mon是月份;dd是天数,hh是小时,mm是分钟,ss是秒,zzz是时间标准的缩写,如CST等,yyyy是年 |
第五章,类子间的关系:
关系概述:
一,继承:(减少代码冗余量,重复用一些好的类,减少重复的代码的编写)
1.也称为泛化,其基本思想是基于某个父类(基类,超类)的扩展,指定一个新的子类(派生类),子类可以继承父类的原有属性与方法,也可以增加父类所不具备的属性和方法,或者直接重写父类中的某些方法。重写(覆盖)就是在子类中将父类的成员方法名保留,重写方法的实现内容,更改成员方法的存储权限,或是修改成员方法中的返回值类型。。还有一种特殊的重写方式,子类和父类的成员方法返回值,方法名称,参数类型及个数完全相同,不同的是方法实现内容,这种特殊重写方式被称为重构。在java中使用extends关键字来标识两个类的继承关系。一个类不能继承多个类。但可以通过实现多个接口来弥补。语法 [访问符][修饰符] class 子类 extends 父类{}
2. 在重写父类方法时,修改方法的修饰权限只能是从小范围到大范围,即确保父类的实例可以访问子类的同名方法。
3.在继承的机制中,创建一个子类对象,将包含的一个父类子对象,这个对象与父类的创建是一样的,两者的区别是后者来自外部,而前者来自子类对象内部,当实例化子类对象时,父类对象也被实例化。即在实例化子类对象时,Java编译器也会在子类的构造方法中调用父类的无参构造方法(仅限于子类无参构造方法(自动调用),有参构造函数不能被自动调用,只能依赖super()显式调用)。即首先要实例化父类的对象,然后在实例化子类对象。所以在子类构造方法访问父类的构造方法之前,父类已经完成了实例化操作。
4.如果要使用finalize()方法对象进行清理,需要确保子类的finalize()方法的最后一个动作是调用父类的finalize()方法,以保证当垃圾回收对象占用内存时,对象的所有部分都能被正常终止。
5.对象类型的转换:向上转型(把子类对象赋值给父类类型的变量),向下转型(将父类对象赋予子类对象时,需要强制转换为子类型 :子类名 子类对象=(子类名) 父类对象,将父类强制转化为某个子类对象,称为显示类型转换 (必须使用))
6.使用instanceof操作符判断对象类型,当程序执行向下转型操作的时候,如果父类对象不是子类对象的实例,就会发生异常,所以在执行向下转型之前需要养成一个习惯,利用instanceof判断父类对象是否为子类对象的实例,可以使用instanceof操作判断是否一个类实现了某个接口和一个对象是否属于一个实例。语法:某类对象的引用 instanceof 某个类;返回类型为boolear值。instanceof为Java的关键字,在java中关键字都小写。
二,多态
Java引用变量有两个类型:编译时类型(由声明该变量所使用的类型决定)和运行时类型(由实际赋给该变量所使用的对象决定),编译时类型与运行时类型不一致,称为多态。对象类型的转换。
一般将继承父类的子类对象赋值给父类引用变量,也可以使用父类构造一个子类实例对象
二般方法重写。不能重写静态方法,
super关键字(代表父类对象):在子类的构造方法中调用父类的构造方法super(实参);,在子类方法中访问父类的属性或方法super.方法/属性。若在子类的构造方法中没有明确写明调用父类的构造方法,则系统会自动调用父类不带参数的构造方法,即执行super()方法,当子类的属性与父类的属性同名时,可以使用super.方法名()的方式来访问父类的方法,
final关键字:表示不可改变的,最终的,用于修饰变量(常量),方法(最终方法,不可被子类重写)和类(最终类,不可被子类继承)。
其他关系:
依赖关系:在一个类的方法中操作另一个类的对象,称其依赖于 第二个类。
关联关系:一个类中使用另一个类的对象作为该类的成员变量。
聚合关系:是关联关系的一种特例,体现的是整体与部分。一个类中的成员变量为另一个类的对象数组。
组成关系:整体和部分不可分离的关联关系。一个类中的成员变量为另一个类对象。
内部类:
在一个类体之内在定义一个类,外层类称为外部类,内层类称为内部类,内部类是外部类的一个成员,依附于外部类。内部类能够隐藏起来,不为同一包的其他类访问,内部类可以访问所在外部类的所有属性。在回调方法处理中,匿名内部类尤为便捷,特别是事件处理经常使用。Java内部类主要有成员内部类,局部内部类,静态内部类,匿名内部类四种。
1,成员内部类:在内部类中可以随意使用外部类的成员变量和成员方法,内部类的实例一定要绑在外部类的实例上。即从外部类中初始化一个内部类对象,那么内部类对象就会绑定在外部类对象上。
内部类的对象实例化操作必须在外部类或者外部类的非静态方法中实现,在外部类中不可以直接调用内部类的类方法和类成员变量,需要内部类对象或对象的引用来调用,即内部类的成员只有在内部类的范围之内是可知的,不能被外部类使用。且内部类不可以定义静态成员,如果硬要在外部类和非静态方法之外实例化内部类对象。需要使用外部类,内部类的形式指定该对象的类型。
即 : 外部类.内部类 内部对象名=外部类对象.new 内部类(); 不能在new操作符之前使用外部类名称实例化内部类对象,使用外部类的对象创建内部类。即没有外部类时不会有内部类,内部类对象依赖于外部类对象。
使用this关键字获取内部类与外部类的引用:在内部类中使用:this.内部类变量;可以调用内部类变量,使用:外部类名.this.外部类变量;可以调用外部类变量。
在含有成员内部类的代码编译后,会生成两个class文件:一个是外部类的:外部类.class文件,另一个是内部类的:外部类.$内部类.class。
2,局部内部类:在方法中或者任意作用域中定义的类,局部内部类不能用public或private 访问修饰符进行声明,作用域被定义在该类的方法块中,局部内部类可以访问它的外部类的所有成员,外部类则不可以访问局部内部类。还可以访问方法体中的final变量。
3,匿名内部类:语法 return new l类名(){};,匿名内部类不能有构造方法,不能定义任何静态成员,方法和类,非静态的可以定义,只能创建匿名内部类的一个实例,一个匿名内部类一定跟在new后,创建其实现的接口或父类的对象。
4,静态内部类:在内部类前添加修饰符static,static类可以声明static成员,静态内部类不可以使用外部类的非静态成员,创建静态内部类的对象,不需要其外部类的对象,不能从静态内部类中的对象访问非静态外部类的对象。静态内部类的作用
public class MainInStaticClass {
static class Main{
static void main() {
//将主方法写到静态内部类中,从而不必为每个源文件都这种一个类似的主方法
new MainInStaticClass().print();
}
}
public static void main(String[] args){
new MainInStaticClass().print();
}
public void print(){
System.out.println("main in static inner class");
}
}
public class TestMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
// new MainInStaticClass().print();
MainInStaticClass.Main.main();
new MainInStaticClass.Main(); } }
5,内部类的继承:内部类的继承需要设置专门的语法:
public class 子类名 extend 父类的外部类名.父类名{
public 子类名(父类的外部类名 对象名){
对象名.super();
}}
class 父类的外部类名{ class 父类名{ }}
6,单例模式(Singlenton 设计模式):
特点:单例类只能有一个实例,必须自己创建自己唯一的实例,必须给其它对象提供实例。
懒汉式单例,在第一次调用的时候实例化自己:
public class Singleton{
private Singleton(){}
private static Singleton single=null;
public static Singleyon getInstance(){
if(sing==null)
single=new Singleton();}}
静态内部类:
public class Singleton{
private static class Lazy{
private static final Singleton INSTANCE=new Singleton();}
private Singleton(){}
public static final Singleton getInstance(){
return LAZY.INSTANCE;
}
}
饿汉式单例类,在初始化时,自行实例化。
public class Singletonon1{
private Singleton1(){}
private static final Singleton1 single=new Singleton1();
public static Singleton1 getInsttance(){
return single;
}
}
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。
在创建的同时就已经创建好了一个静态的对象供系统使用,以后不再给变,所以天生是线程安全。
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。或者说:一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题,那就是线程安全的。
第六章,抽象类与接口
1,抽象类:
抽象类是对问题领域进行分析后得到的抽象概念,是对类不可在继承得到的相同部分的抽象描述,(避免子类设计的随意性)抽象类一般为父类,且不可以实例化对象,可以定义成员变量与抽象方法。语法: [访问符] abstract class 类名 { [访问符] absrtact <返回值类型> 方法名 ([参数表列]);……}。
抽象类不能被实例化,即使抽象类中不包含抽象方法也不行,一个抽象类中可以含有多个抽象方法,也可以含有已实现的方法,但抽象方法没有方法体,抽象类可以包含 成员变量以及构造方法,不能通过构造方法创建实例,可以在子类创建实例时调用,抽象类可以继承为抽象类。继承了抽象类的抽象类可以不实现方法(因为做不到哎)。
abstract关键字不能用来修饰成员变量和构造方法,abstract关键字修饰的方法必须被其子类重写才有意义,否者永远不会有方法体,因此,抽象类不可以定义为private,abstract也不能与static,final或native(方法只可以调用,但是不能编写)同时修饰同一方法。抽象类被继承后需要实现其所有的抽象方法,即继承的子类中要对抽象方法进行覆盖,
2,接口:
接口解决类不能同时继承多个父类及选择性的继承父类 ,接口定义了某一批类所需要遵守的公共行为规范,只规定这批类必须提供的某些方法,而不提供任何实现,体现规范和实现分离的哲学。让系统的各模块之间面向接口耦合,是一种松耦合的设计,即模块之间联系甚少,可以多次单独利用,增强系统的可扩展性。
java允许一个类实现多个接口,使用关键字 interface 进行定义。语法 [访问符] interface 接口名[ extends 父接口1,父接口2……]{//接口体},访问符为public或默认。
一个接口可以继承多个父接口,但不可以继承类,在接口体里可以包含静态常量,抽象方法,内部类,内部接口,以及枚举的定义,java8允许默认方法与类方法。 在接口内的定义的常量及方法都被默认为public。在接口中定义的任何常量都默认为 static和final。如果不是定义的默认方法,系统将默认为普通方法增加 public abstract进行修饰,即抽象方法,不能有方法实现。
在JAVA8中,可以定义默认方法,需要用default关键字修饰,不能使用static关键字修饰,不能使用接口来调用默任方法,默认方法必须有方法实现。也可以定义类方法,类方法必须用static修饰,不能使用default修饰,也必须要有方法体,可以通过接口调用方法。
在接口中可以定义内部类,内部接口以及内部枚举都默认为public static 。
实现接口:接口不能直接实例化,但可以使用接口声明引用类型的变量,该变量可以是实现类的实例对象(向上转型),一个类可以实现一个或多个接口,语法:[访问符] class 类名 implements 接口1 [,接口2,……]{//类体}。一个类在实现一个或多个接口时,这个类必须完全实现这些接口中定义的所有抽象方法,否则该类必须为抽象类,类实现某个接口时,该类将会获得接口中定义的常量,方法等,因此可以将实现接口理解为一种特殊的继承,接口的默认方法通过“对象.默认方法()”形式访问。而接口的类方法则可以通过“接口.类方法访问”。
接口的继承:
接口支持多重继承,当一个接口继承父接口时,该接口将会获得父接口中定义的所有抽象方法,常量。: interface 接口1 extends 接口1,接口2{}接口1继承接口2,接口3。
在一个Java源文件中可以有多个接口和类,但最多只能有一个接口或类是public,且该源文件的文件名必须与public所修饰的接口或类名一致。
面向接口的编程:充分利用接口能够降低程序各模块之间的耦合,提高可扩展性及可维护性,许多架构设计都倡导“面向接口编程”。
接口与抽象类的区别
接口 | 抽象类 | |
相同点 | 不能被实例化,都可以向上转型,都包含抽象方法,在实现接口或者继承抽象类时要实现全部方法, | |
不同点 | 多继承,公共行为规范(总纲),接口除默认方法与类方法外不能提供方法体,且成员必须为静态常量, | 单继承,是不可被继承的抽象描述(模板式设计),抽象类可以包含任意的成员变量,构造函数,构造函数可以初始化操作 |
第七章,异常
异常概述:程序中的错误可分为语法,逻辑,运行时错误。程序在运行时的错误被称为异常。
THrowable:是所有异常类的父类,Error与Exception都继承此类,
Error(错误):一般指与虚拟机相关的问题,如系统奔溃,虚拟机错误,动态链接失败等,即无法恢复或捕捉的错误,导致应用程序中断。
Exception(异常):因程序编码错误或外在因素导致的问题,能够被系统捕捉并进行处理,避免程序非正常中断。Exception异常从编程角度分为两种:非检查型异常+检查型异常。
1非检查型异常:编译器不要求强制处置的异常,可以避免,RuntimeException及其所有子类都属于非检查型异常。
2检查型异常:编译器要求必须处理的异常,该异常是程序运行时因外界因素而导致的,除RuntimeException类外Exception的所有子类都是检查型异常。
ArrayStoreException:数组中包含不兼容的值抛出的异常。
NoSuchFieldException:字段未找到异常。
NoSuchMethodException:方法未找到抛出异常。
IllegalAccessException:不允许访问异常。
Securityexception:安全性异常。
IllegalArgumentException:非法参数异常。
Instantiationexception:当应用程序视图使用class类中的newInstance()方法创建一个实例时,而自定的类对象无法被实例化,抛出该异常。
异常处理机制:为使可能出现异常的程序也能正常运行,需要对异常进行相关的处理操作。Java异常处理机制让程序具有良好的容错性,在程序出现意外情况时,系统会自动生成一个异常对象来通知程序对相应的异常对象作出处理。
Java提供的异常处理机制有两种:
捕获异常:
1。使用try……catch捕获异常。将可能出现的异常的代码放到try语句中进行相应的隔离,如果遇到异常,程序会停止执行try块的代码,自动生成一个异常对象,该异常对象被提交给Java运行时环境(抛出异常),Java运行时环境收到异常对象时,跳到catch块中进行处理(即与catch中的异常对象一一匹配),匹配成功执行相应的catch块语句(捕获异常)。
语法:try{//可能出现异常的代码}catch(异常类 异常对象){//该异常类的处理代码}……/可以有多个catch语句。
所有异常对象都包含一下几个常用的方法用于访问异常信息:
getMessage() | 返回该异常的详细描述字符串(类型,性质) |
printStackTrace() | 将该异常的跟踪栈信息输出到标准错误输出 |
printStackTrace(PrintStream s) | 将该异常的跟踪栈信息出现在程序中的位置输出到指定的输出流 |
getStackTrace() | 返回该异常的跟踪栈信息 |
toString() | 返回异常发的类型与性质 |
在执行多catch语句时,当异常对象被其中的一个catch语句捕获时, 剩下的catch语句将不
会进行匹配。在安排顺序时,首先应该捕获一些子类异常,然后在捕获父类异常。即父类异常必须放到子类的后面,同一级不影响。
try……catch……finally语句:防止try中出现异常无法回收物理资源,finally块中放回收代码,显示回收在try中打开的物理资源。不管try块中是否出现异常,也不管catch块中是否执行return语句,finally总会被执行(不被执行的情况:finally语句发生异常,使用了System.exit(0)语句,线程死亡,关闭cpu)。
语法:try{//可能发生异常的代码}catch(异常类 异常类对象){//异常类的处理代码}……finally{//资源回收语句}。try块时必须的,catch块与finally块时可选的,即try……finally或try……catch……finally(顺序不能颠倒);
自动关闭资源的try语句:
语法 try{//声明,初始化资源代码}{//业务实现代码(可能发些异常的)}后面可以没有catch块。例try(EileInputStream fis=new FileInputStream("asd.txt")){},jdk1.7中新加。
嵌套的try...catch语句,使用嵌套的try...catch语句,当内部的try块没有遇到匹配的catch块则检查外部的catch块。
多异常捕获:语法:try{//业务实现代码(可能发生异常)}catch(异常类1[|异常类2|异常类3……] 异常对象){//多异常捕获处理代码}。不同异常类之间用 | 隔开。多异常捕获时,异常变量默认是常量,因此不能对该异常变量重新赋值。
抛出异常:
java中使用throw或throws关键字。
thorw:使用throw抛出一个异常对象,当程序出现异常时,系统会自动抛出异常,也可以使用throw语句自动抛出一个异常。throw语句抛出的不是异常类,而是一个异常实例对象,且每次只能抛出一个异常实例对象。语法:throw new 对象名();
thorws:使用throws声明抛出异常。使用throws声明一个异常序列:当前方法不知道如何处理异常时,该异常应有上一级调用者进行处理,可在定义该方法时使用throws声明抛出异常。语法:[访问符] <返回类型> 方法名([参数表列])throws 异常类A [,异常类B,异常类C,……]{}.throws只是抛出异常,还需要进行捕获。如果是Error或者RuntimeException或他们的子类,可以不用throws关键字来声明要抛出的异常,编译仍能通过,运行时系统抛出。
自定义异常:例 public class AgeException extends Exception{public AgeException(){} public AgeException (String srt){super();}}
在自定义异常时,如果总是在程序运行时产生异常,且不易预测异常将在合何时,何地发生,则可以将该异常定义为非检查型异常(继承RuntimeException);否则定义为检查型异常(继承Exception)。
一个方法被覆盖时,覆盖它的方法必须抛出相同的异常或异常的子类。如果父类抛出多个异常,则覆盖方法必须抛出那些异常的一个子集,不能抛出新异常。
第八章:泛型与集合
从JDK5.0开始,Java引入“参数化类型”的概念,泛型指将数据类型参数化,即在编写代码的时候将数据类型定义成参数,在使用之前在进行指明。
泛型提高了代码的重用性,是的程序更加灵活,安全和简洁。泛型的好处在在程序编译期会对类型进行检查,捕捉类型不匹配错误,以免引起ClassCastException异常。
泛型常使用在类接口,和方法的定义中。分别称为泛型类,泛型接口和泛型方法。泛型为引用类型,在内存堆中。
定义泛型类:[访问符] class 类名<类型参数表列(逗号隔开)>{//类体}类型参数为占位符一般用大写T,U,V等。
实例化泛型类:类名<类型参数列表>对象 = new 类名<>(构造方法列表);菱形语法,
通配符:通配符由?表示一个未知类型,从而解决类型被限制,不能动态根据实例进行确定。public static void myethod(Generic<?> g){ }
有界类型:有时需要对类型参数的取值进行一定程度的限制,Java提供有界类型限制参数范围,
1,使用extends声明类型参数的上界,即限制此类参数必须继承自指定的父类的子类或父类本身,称为上界(upper bound)。可以在定义泛型时使用:类名<参数类型 extends 父类>,也可以在使用泛型时指定类名<?extends 父类>。一般用来读。
2,使用super声明参数类型的下界。限制此类型参数必须是指定的类型本身或其父类,直至Object类,称为下界(lower bound),类型参数下界在使用泛型时使用:泛型类<? super 类型>,不可用于定义时。很少用。一般用来写。
泛型的限制:泛型的类型参数只能是类类型,不能是(简单)基本类型,可以为自定义类;同一个泛型类的个版本(参数类型)的实例是不兼容的,定义泛型时,类型参数只是占位符,不能实例化。T new T();是错误的。可以使用泛型机制声明一个数组,不能实例化泛型数组,除非是无上界的类型通配符,即 类名<?>[] a=new 类名<?>[10] 是被允许的。泛型类不能继承Throwable及其子类,即不能为异常类,不能抛捕异常。
第九章,集合的概述:
集合框架:
Java.util包中提供了一些集合类,这些集合类又被称为容器,是一些常用的数据结构,例如,队列,栈,链表等。
常用的集合List集合,Set集合,Map集合。
从JDK5.0开始为了处理多线程环境下的并发安全问题,又在Java.util.concurrent包下提供了一些多线程支持的集合类,
Java的集合类主要由两个接口派生而出:Collection和Map这两个接口派生出一些接口或实现类。
Clooection接口有3个子接口:
1,Set接口:无序,不可重复的集合;
2,Queue接口:队列集合;
3,List接口:有序,可以重复的集合。
所有的Map的实现类用于保存具有映射关系的数据,即Map保存的每项数据都是由key—value键值对组成的。Map中的key用于标识集合中的每项数据,是不可重复的。可以通过key来获取Map集合中的数据项。
Java中集合分为三大类:
Set集合:将一个对象添加到Set集合时,Set集合无法记住添加的顺序,因此Set集合中的元素不能重复,否则系统无法识别该元素,访问Set集合中的元素只能根据元素本事进行访问。
List集合:与数组类似,List集合可以记住每次添加元素的顺序,因此可以根据元素的索引访问List集合中的元素,List集合中的元素可以重复且长度是可变的。
Msp集合:每个元素都是由key-value键值对组成的,可以根据每个元素的key来访问对应的value,Map集合中的key不能允许重复,value可以重复。
迭代器接口(Iterator):可以采用统一的方式对Collection集合中的元素进行遍历开发,从JDK5.0后开始增加Iterable新接口,该接口是Collection的父接口,因此所有实现了Iteraable的集合类都是可以迭代的。都支持foreach循环遍历,Iterable接口中的iterator()方法可以获取每个集合自身的迭代器Iterator,Iterator是集合的迭代器接口,定义了常用的迭代方法,用于访问,操作集合中的元素。
Iterator接口中的方法
default void forEachRemaining(Consumer< ? super E>action) | 默认方法,对所有元素执行指定的动作 |
boolean hasNext() | 如果仍有元素可以迭代,则返回 true。 |
E next() | 返回可访问的下一个元素 |
void remove() | 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。该方法必须紧跟在一个元素的访问后执行 |
Collection接口:
是Set,Queue和List接口的父接口,该接口中定义的方法可以操作这三个接口中的任一个集合。
Collection接口中常用方法
Boolean add(E obj) | 添加元素,成功返回true |
boolean addAll(Collection<?extends E>c) | 添加集合c的所有元素 |
void clear() | 清除所有元素 |
boolean contains(Object obj) | 判断是否包含指定的元素,包含则返回true |
boolean containsAll(Collection<?>c) | 判断是否包含集合c的所有元素 |
int hashCode() | 返回该集合的哈希码 |
boolean isEmpty() | 判断是否为空,若空返回true |
Iterato<E>itertor() | 返回集合的迭代接口 |
boolean removeAll(Collection<?>c) | 移除集合c的所有元素 |
boolean remove(Object obj) | 移除元素 |
boolean retainAll(Collection<?> c) | 仅保留集合c的所有元素,其他元素都删除 |
int size() | 返回元素个数 |
Object[] toArray() | 返回包含集合所有元素的数组 |
<T>Y[]toArray(T[] a) | 返回指定类型的包含集合所有元素的数组 |
使用Collection接口需要注意以下几点:
- add(),addAll(),remove(),removeAll()和retainAll()方法可能会引发不支持该操作的UnsupportedOperationException异常。
- 将一个不兼容的对象添加到集合中时,将产生ClassCastException异常
- Collection接口没有提供获取某个元素的方法,但是可以通过iterator()方法获取迭代器来遍历集合中的所有元素
- 虽然Collection中可以存储任何Object对象,但不建议在同一个容器中存储不同类型的对象,建议使用泛型增强集合的安全性。以免引起ClassCastException异常。
List接口及其实现类:
List是Collection接口的子接口,可以使用Collection接口中的全部方法,因此List是有序的,可重复的集合,所以List接口中又增加一些根据索引操作集合元素的方法。
List接口中的方法
void add(int index,E element) | 在列表的指定索引位置插入指定元素 |
boolean addAll(int index,Collection<? extends E >c) | 在列表的指定索引位置插入集合c所有元素 |
E indexOf(Object o) | 返回列表中第一次出现指定元素的索引,如果不包含该元素返回-1 |
E get(int index) | 返回列表中指定索引位置的元素 |
int lastIndexOf(Object o) | 返回列表中最后出现指定元素的索引,如果不包含该元素返回-1 |
E remove(int index) | 移出指定索引位置上的元素 |
E set(int index,E element) | 用指定的元素替换列表中指定的索引位置的元素 |
List Iterator<E>listIterator() | 返回列表元素的列表迭代器 |
List Iterator<E>listIterator(int index) | 返回列表元素的列表迭代器 |
List<E>subList(int fromIndex,int toIndex) | 返回列表指定的fromLindex(包括)和toIndex(不包括)之间的元素列表 |
List 集合默认按照元素添加顺序设置的索引,索引从0开始,使用无效的索引时将产生IndexOutOfBoundsException异常。
ArrayList和Vector是List接口的两个典型实现类,
完全支持List接口的所有功能方法,ArrayList称为“数组列表”,Vector称为“向量”,都是基于数组实现的列表集合,是一个动态的,长度可变的,并允许再分配Object[] 数组。
ArrayList和Vector都提供如下两种方法对Object[]数组进行重新分配
ArrayList和Vector类中的方法
void ensureCapacity(int minCapacity) | 增加容量,使Object[]数组的长度增加到大于或等于minCapacity |
void trimToSize() | 调整容量,释放Object[]数组中没有用到的空间,使数组长度为当前元素的个数,减少集合对象所占用的空间。 |
ArrayList与Vector的区别:
Array是非线程安全的,当多个线程访问同一个ArrayList集合时,如果多个线程同时修改ArrayList集合中的元素,则程序必须手动保证该集合的同步性;
Vector是线程安全的,程序无序手动保证该集合的同步性。所以Vector的性能要比ArrayList低,在实际应用中既要保证线程安全又要保证性能,可以使用Collection工具将ArrayList变成线程安全的.
Vector还提供一个Stack子类,模拟栈的数据结构,栈具有先进后出的特性。
Stack类中的方法
E peek() | 查看栈顶元素,但并不是将该元素从栈中移除 |
E pop() | 出栈,及移除栈顶元素,并将该元素返回 |
E push(E item) | 入栈,即将指定的item元素压如栈顶 |
Set接口及其实现类:
Set接口不能记住添加元素的顺序,不允许包含相同的元素,Set接口继承Collection接口,没有额外方法,Set接口常用类包括:HashSet,TreeSe和EnumSet。
HashSet:是Set的典型实现类,大多数使用Set集合时都使用,使用Hash算法来存储集合中的元素。允许null,由HashMap实例支持。
TreeSet:采用Tree树的数据结构来存储集合元素,集合中的元素处于排序状态,TreeSet支持自然排序和定制排序。默认情况下自然排序。
EnumSetSet:所有元素为枚举类型。有序,按照枚举值进行排序。
HashSet及其子类都采用Hash算法来决定集合中元素的存储位置,并通过Hash算法来控制集合的大小,Hash表中可以存储元素的位置称为桶(bucket),单个桶只存储一个元素。此时性能最佳,Hash算法可以根据HashCod值计算出桶的位置,并从桶中取出元素,但当发生Hash冲突时,单个桶会存储多个元素,元素以链表形式存储,
Queue接口及其实现类
队列Queuee通常以“先进先出(FIFO)”的方法排序各个元素,最先入队的元素最先出队,Queue接口继承Collection接口,提供对列的插入,提取,和检查操作,且每个操作都存在两种形式,1操作失败抛出异常,2操作失败时返回一个特殊值null或false。
Queue接口中的方法
E element() | 获取队头元素,但不移除此队列的头 |
boolean offer(E e) | 将指定元素插入到此队列,当队列有容量限制时,该方法要优于add()方法,后者可能无法插入元素,而只是抛出一个异常 |
E peek() | 查看队头元素,但不移除此队列的头。如果队列为空,则返回null |
E poll() | 获取并移除此队列的头,如果队列为空,则返回null |
E remove() | 获取并移除此队列的头 |
Deque(double ended queue,双端队列)是Queue的子接口,支持在队列的两端插入和移除元素,Deque接口中定义在双端队列两端插入,移除和检查元素的方法,
Deque接口中的方法
void addFirst(E e) | 将指定元素插入此双端队列的开头,插入失败将抛出异常 |
void addLast(E e) | 将指定元素插入此双端队列的末尾,插入失败将抛出异常 |
E getFiret() | 获取但不移除此双端队列的第一个元素 |
E getLast() | 获取但不移除此队列的最后一个元素 |
boolean offerFirst(E e) | 将指定的元素插入到此双端对列的开头 |
boolean offerLast(E e) | 将指定的元素插入到双端对列的末尾 |
E peekFirst() | 获取但不移除此双端队列的第一个元素,如果队列为null,则返回null |
E peekLast() | 获取但不移除此双端队列的最后一个元素,如果队列为null,则返回null |
E pollFirst() | 获取并移除此双端队列的第一个元素,如果为空,返回null |
E pollLast() | 获取并移除此双端队列的最后一个元素,如果为空,返回null |
E removeFirst() | 获取并移除此双端队列的第一个元素 |
E removeLast() | 获取并移除此双端队列的最后一个元素 |
链接链表是LinkedList是Deque和List两个接口的实现类,具有队列和列表两种特性。是最常使用的集合之一,LinkedList不是基于线程安全的,如果多个线程同时访问一个LinkedList实例,而其中至少有一个线程从结构上修改该列表时,则必须由外部代码手动保持同步。
ArrayDeque 称为"数组双端队列",是Deque接口的实现类,ArrayDeque没有容量限制,可以根据需要增加容量,ArrayDeque不是基于线程安全的,在没有外部代码同步时,不支持多个线程的并发访问;ArrayDeque禁止添加null元素;ArrayDeque在用作堆栈时快与Stack(栈),在用作队列时快与LinkedList。
PriorityQueue是Queue接口的实现类,是基于优先级的,无界队列,称为优先级队列,优先级队列的元素按照其自然顺序进行排序,或定制排序,优先级队列不允许使用空值,依靠自然顺序的优先级队列不允许插入不可比较的对象。
Map接口及其实现类:
Map接口是集合框架的另一个根接口,与Collection接口并列。Map是以key-value键值对映射关系存储的集合,
Map接口中的方法
void clear() | 移除所有映射关系 |
boolean containsKey(Object key) | 判断是否包含指定键的映射关系,包含则返回true |
boolean containsValue(Object key) | 判断是否包含指定值的映射关系,包含返回true |
Set<Map,Entry<K,Y>>entrySet() | 返回此映射中包含的映射关系的Set视图 |
V get(Object key) | 返回指定键所映射的值 |
int hashCode() | 返回此映射的哈希码值 |
boolean isEmpty() | 判断是否为空,为空则返回true |
Set<K>keySet() | 返回此映射中包含的的键的Set视图 |
V put(K key,V value) | 将指定的值与此映射中的指定键关联 |
void putAll(Map<? extends K,? extends V > m) | 从指定映射中将所有映射关系复制到此映射中 |
V remove(Object key) | 移除指定键的映射关系 |
int size() | 返回此映射中的关系数,即大小 |
Collection<V>values() | 返回此映射中包含的值的Collection视图 |
HashMap和TreeMap是Map体系中的两个常用的实现类。
HashMap是基于哈希算法的Map接口的实现类,该实现类提供所有映射操作,并允许使用null键和null值,但不保证映射的顺序,无序的映射集合。
TreeMap是基于“树”结构来存储的Map接口的实现类,可以根据其键的自然顺序进行排序,或定制排序方式。不允许使用null键和null值,当使用get()方法获取元素时,没有指定键时返回null。
集合的转换
Java集合框架有两大体系Collection和Map,可以将Map集合转换为Collection集合。
将Map集合转换为Collection集合有三个办法。
entrySet():返回一个包含Map中元素的集合,每个元素都包含键和值。
keySet():返回Map中所有的键的集合。
values():返回Map中所有值的集合;
集合工具类:
Collections工具类提供了一些对Collection集合常用的静态方法。
Collections工具类
static <T> void copy(List<? super T > dest,List <? extends T > src ) | 将所有元素从一个列表复制到另一个列表 |
static <T>void fill(List<? super T> list,T obj) | 使用obj替换list中的所有元素 |
static <T extends Object&Comparable<? super T >>T max(Collection<? extends T> coll) | 根据自然排序,返回给定集合的最大元素 |
static <T> T max(Collection<? extends T >coll ,Comparator<? super T>comp) | 根据指定的比较器排序,返回给定集合的最大元素 |
static <T extends Object&Comparable<? super T>>T min(Collection<? extends T >coll) | 根据自然排序,返回给定集合的最小元素 |
static <T> T min(Collection<? extends T > coll,Comparator<? super T>comp) | 根据指定的比较器排序,返回给定集合的最小元素 |
static <T extends Collection<? super T>>void sort(List<T> list) | 根据自然排序,对指定列表按升序进行排序 |
static <T> void sort(List<T> list,Comparator<? super T> c) | 根据指定的比较器排序,对指定列表排序 |
static void swap(List<?> list,int i,int j) | 在指定列表的指定位置交换元素 |
static <T> Collection<T> synchronizedCollection(Collevtion<T> c) | 返回线程安全支持的同步collection |
static <T> List<T> synchronizedList(List<T> list) | 返回线程安全支持同步的列表 |
static <K,V> Map<K,V> synchronizeMap(Map<K,V>m) | 返回线程安全支持同步的列表 |
static <T> Set<T> synchronizedSet(Set<T> s) | 返回线程安全支持同步的set |
使用Collections工具类进行排序时,集合中的元素必须是Comparable可比较,Java提供了Comparable接口,该接口只有一个CompareTo()比较方法。
自然比较方法:如果一个类实现Comparable接口,则该类的对象就可以整体进行比较排序,这种排序方式称为类的“自然排序”,compareTo()方法被称为“自然比较方法”。
Arrays工具类则提供了针对数组的各种静态方法。
Arrays工具类中常用的静态方法
static intbinarySearch(Object[] a,Object key) | 使用二分搜索法搜索指定对象数组,已获得指定对象 |
static <T> int binarySearch(T[] a,T key,Comparator<? super T > c) | 使用二分搜索法指定泛型数组,获得指定数组 |
static <T> T[] copyOf(T[] original,int newLength) | 复制指定的数组,如有必要截取或用null填充 |
static <T> T[] copyOfRange(T[] original,int from ,int to) | 将指定数组的指定范围复制到一个新数组 |
static void fill(Object [] a ,Object val) | 将指定的值填充到指定数组的每个元素 |
static void hashCode(Object[] a ) | 基于指定数组内容返回哈希码 |
static void sort(Object [] a) | 根据元素的自然顺序对指定指定数组进行升序排序 |
static <T> voidsort(T[] a,Comparator<? super T > c) | 根据指定比较器对指定数组进行排序 |
static String toString(Object[] a) | 返回指定数组内容的字符串表示形式 |
Java-Arrays类常用方法详解
一、Arrays类的定义 Arrays类位于 java.util 包中,Arrays类的常用方法
1、Arrays.asList(T… data) 注意:该方法返回的是Arrays内部静态类ArrayList,而不是我们平常使用的ArrayList,,该静态类ArrayList没有覆盖父类的add, remove等方法,所以如果直接调用,会报UnsupportedOperationException异常
将数组转换为集合,接收一个可变参数
List list = Arrays.asList(1, 2, 3);
list.forEach(System.out::println); // 1 2 3
Integer[] data = {1, 2, 3};List list = Arrays.asList(data);
list.forEach(System.out::println); // 1 2 3
如果将基本数据类型的数组作为参数传入, 该方法会把整个数组当作返回的List中的第一个元素
int[] data = {1, 2, 3};
List<int[]> list = Arrays.asList(data);
System.out.println(list.size());
// 1System.out.println(Arrays.toString(list.get(0)));
// [1, 2, 3]
2、Arrays.fill() Arrays.fill(Object[] array, Object obj)用指定元素填充整个数组(会替换掉数组中原来的元素)
Arrays.fill(Object[] array, int fromIndex, int toIndex, Object obj)用指定元素填充数组,从起始位置到结束位置,取头不取尾(会替换掉数组中原来的元素)
Integer[] data = {1, 2, 3, 4};
Arrays.fill(data,9);
System.out.println(Arrays.toString(data)); // [9, 9, 9, 9]
Integer[] data = {1, 2, 3, 4};
Arrays.fill(data, 0, 2, 9);
System.out.println(Arrays.toString(data)); // [9, 9, 3, 4]
3、Arrays.sort()
Arrays.sort(Object[] array)对数组元素进行排序(串行排序)
Arrays.sort(T[] array, Comparator<? super T> comparator)使用自定义比较器,对数组元素进行排序(串行排序
String[] data = {“1”, “4”, “3”, “2”};
System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
Arrays.sort(data);
System.out.println(Arrays.toString(data)); // [1, 2, 3, 4]
String[] data = {“1”, “4”, “3”, “2”};
System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
// 实现降序排序,返回-1放左边,1放右边,0保持不变
Arrays.sort(data, (str1, str2) -> {if (str1.compareTo(str2) > 0) {
return -1;
} else {
return 1;
}
});
System.out.println(Arrays.toString(data)); // [4, 3, 2, 1]
Arrays.sort(Object[] array, int fromIndex, int toIndex)对数组元素的指定范围进行排序(串行排序)
Arrays.sort(T[] array, int fromIndex, int toIndex, Comparator<? super T> c)使用自定义比较器,对数组元素的指定范围进行排序(串行排序)
String[] data = {“1”, “4”, “3”, “2”};
System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
// 对下标[0, 3)的元素进行排序,即对1,4,3进行排序,2保持不变
Arrays.sort(data, 0, 3);
System.out.println(Arrays.toString(data)); // [1, 3, 4, 2]
String[] data = {“1”, “4”, “3”, “2”};
System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
// 对下标[0, 3)的元素进行降序排序,即对1,4,3进行降序排序,2保持不变
Arrays.sort(data, 0, 3, (str1, str2) -> {if (str1.compareTo(str2) > 0) {
return -1;
} else {
return 1;
}});
System.out.println(Arrays.toString(data)); // [4, 3, 1, 2]
4、Arrays.parallelSort() 注意:其余重载方法与 sort() 相同
Arrays.parallelSort(T[] array)对数组元素进行排序(并行排序),当数据规模较大时,会有更好的性能
String[] data = {“1”, “4”, “3”, “2”};
Arrays.parallelSort(data);
System.out.println(Arrays.toString(data)); // [1, 2, 3, 4]
5、Arrays.binarySearch() 注意:在调用该方法之前,必须先调用sort()方法进行排序,如果数组没有排序, 那么结果是不确定的,此外如果数组中包含多个指定元素,则无法保证将找到哪个元素
Arrays.binarySearch(Object[] array, Object key)使用 二分法 查找数组内指定元素的索引值
Object[] object = {1,2,3,4,5,6};
int index = Arrays.binarySearch(object,1);
System.out.println("索引是:"+index);
6、Arrays.copyOf()
Arrays.copyOf(T[] original, int newLength)拷贝数组,产生一个新数组,其内部调用了 System.arraycopy() 方法,从下标0开始,如果超过原数组长度,会用null进行填充
Integer[] data1 = {1, 2, 3, 4};
Integer[] data2 = Arrays.copyOf(data1, 2);
System.out.println(Arrays.toString(data2)); // [1, 2]
Integer[] data2 = Arrays.copyOf(data1, 5);
System.out.println(Arrays.toString(data2)); // [1, 2, 3, 4, null]
7、Arrays.copyOfRange(T[] original, int from, int to)
拷贝数组,指定起始位置和结束位置,如果超过原数组长度,会用null进行填充
Integer[] data1 = {1, 2, 3, 4};
Integer[] data2 = Arrays.copyOfRange(data1, 0, 2);
System.out.println(Arrays.toString(data2)); // [1, 2]
Integer[] data2 = Arrays.copyOfRange(data1, 0, 5);
System.out.println(Arrays.toString(data2)); // [1, 2, 3, 4, null]
8、Arrays.equals(Object[] array1, Object[] array2)
判断两个数组是否相等,实际上比较的是两个数组的哈希值,即 Arrays.hashCode(data1) == Arrays.hashCode(data2)
Integer[] data1 = {1, 2, 3};
Integer[] data2 = {1, 2, 3};
System.out.println(Arrays.equals(data1, data2)); // true
9、Arrays.deepEquals(Object[] array1, Object[] array2)
判断两个多维数组是否相等,实际上比较的是两个数组的哈希值,即 Arrays.hashCode(data1) == Arrays.hashCode(data2)
Integer[][] data1 = {{1,2,3}, {1,2,3}};
Integer[][] data2 = {{1,2,3}, {1,2,3}};
System.out.println(Arrays.deepEquals(data1, data2)); // true
10、Arrays.hashCode(Object[] array) 返回数组的哈希值
Integer[] data = {1, 2, 3};
System.out.println(Arrays.hashCode(data)); // 30817
11、Arrays.deepHashCode(Object[] array) 返回多维数组的哈希值Integer[][] data = {{1, 2, 3}, {1, 2, 3}};
System.out.println(Arrays.deepHashCode(data)); // 987105
12、Arrays.toString(Object[] array) 返回数组元素的字符串形式Integer[] data = {1, 2, 3};
System.out.println(Arrays.toString(data)); // [1, 2, 3]
13、Arrays.deepToString(Object[] array) 返回多维数组元素的字符串形式Integer[][] data = {{1, 2, 3}, {1, 2, 3}};
System.out.println(Arrays.deepToString(data)); // [[1, 2, 3], [1, 2, 3]]
14、Arrays.setAll(T[] array, IntFunction)
Integer[] data = {1, 2, 3, 4};// i为索引值
Arrays.setAll(data, i -> data[i] * 2);
System.out.println(Arrays.toString(data)); // [2, 4, 6, 8]
15、Arrays.parallelSetAll(T[] array, IntFunction Integer[] data = {2, 3, 4, 5};// 第一个元素2不变,将其与第二个元素3一起作为参数x, y传入,得到乘积6,作为数组新的第二个元素// 再将6和第三个元素4一起作为参数x, y传入,得到乘积24,作为数组新的第三个元素,以此类推
Arrays.parallelPrefix(data, (x, y) -> x * y);
System.out.println(Arrays.toString(data)); // [2, 6, 24, 120]
16、Arrays.spliterator(T[] array) 返回数组的分片迭代器,用于并行遍历数组
public class Students {
private String name;
private Integer age;
public Students(String name, Integer age) {
this.name = name;
this.age = age;
}
// 省略get、set方法
}
public static void main(String[] args) {
Students[] data = new Students[5];
IntStream.range(0,5).forEach(i -> data[i] = new Students(“小明”+i+“号”, i));
// 返回分片迭代器
Spliterator spliterator = Arrays.spliterator(data);
spliterator.forEachRemaining(stu -> {
System.out.println("学生姓名: " + stu.getName() + " " + "学生年龄: " + stu.getAge());
// 学生姓名: 小明0号 学生年龄: 0
// 学生姓名: 小明1号 学生年龄: 1
// 学生姓名: 小明2号 学生年龄: 2
// 学生姓名: 小明3号 学生年龄: 3
// 学生姓名: 小明4号 学生年龄: 4 });}
17、Arrays.stream(T[] array) 返回数组的流Stream,然后我们就可以使用Stream相关的许多方法了
Integer[] data = {1, 2, 3, 4};
List list = Arrays.stream(data).collect(toList());
System.out.println(list); // [1, 2, 3, 4]
标签:读书笔记,对象,接口,Arrays,int,应用,字符串,方法,JAVA8 From: https://blog.51cto.com/u_13474506/5931186