admin 管理员组文章数量: 1184232
2024年3月7日发(作者:织梦迷境攻略)
第一章 Java编程环境
1、什么是java,java的诞生?
Java是一种革命性的程序设计语言,用它编写的程序可以在不同类型的计算机上运行。用java语言可以编写applet小程序,可以将这些小程序嵌入到网页中,也可以编写大型应用程序,编写GUI实用程序,编写网络应用程序。
Java的诞生,1941年java的创始人是SUN MicroSystem公司的Jame Gosling 、Bill
joe等人创始的,真正形成是在1942年。
2、java 的语言特点
简单性、面向对象、分布式、解释执行、健壮、安全、体系结构中立、可移植、高性能、多线程、动态性。
3、java程序
用Java可以编写两类程序:一类是嵌入到网页的程序,叫做java applet(java小程序),另一类是通常的对立应用程序,叫做java application(java应用程序)。Java应用程序进一步细分为:一时控制台应用程序(concole application)。它仅支持将字符输出到计算机的屏幕;另一个是窗口式应用程序(windowed application),它能建立和管理多个窗口。
4、java三大平台
J2SE:针对普通pc应用,是java的基础,另外两个领域都以这个为基础,可实现基于操作系统的应用程序。
J2EE:java 2企业版,是一套面向企业应用的体系结构,适用于开发分布式、多层式,以组件为基础,为WEB为基础的应用程序。
J2ME:java版本中最小的一个,目的是作为小型数字设备上开发及部署的应用平台,针对嵌入式设备的,如:手机、股票机等。
5、java环境
Java平台由两部分组成:一是用于实现软件的假想计算机,叫做java虚拟机(JVM);另一个叫做java应用程序编程接口(java API),它是一个软件组件的集合。
Java编译器:将java源代码转换成由字节代码组成的二进制程序,这些字节码是虚拟机的机器指令。Java解释器:检查并解释该程序的源代码,以确定该字节码的未曾被篡改过。并可以顺利执行,然后在执行字节代码在虚拟机内规定的动作。
Java字节代码执行的两种方式:一是interpreter解释方式;二是just-initiative-time即时编译。
6、java程序设计环境
一、JDK、JRE的介绍
JDK是java的核心,包括java的运行环境,一堆java工具和java基础的类库()。它也包含JRE,但是不是系统内部公共的。JRE跟java虚拟机一个概念,它包括java虚拟机、java平台核心类和支持文件,不包含开发工具—编译器、调试器和其他工具。
二、Java SDK 的安装
配置Java 运行环境(假设将java安装到E盘的根目录下)
1)、先安装java JDK,一般系统会默认的安装路径是:c:program filejava。注意:在安装JDK的时候文件夹的命名不支持有空格、标点。
2)、设置环境变量
右击“我的电脑”?“属性”?“高级”?“环境变量”在“系统变量”或“用户变量”中编
辑path,在变量值中加入“;E:j2sdk1.4.2_01bin”,新建变量名“classpath”,变量值是“.;E:j2sdk1.4.2_01bin”,新建变量名“JAVA-HOME”,变量值为“E:j2sdk1.4.2_01”。
说明:(1)path 是让Java 程序设计者在任何目录下都可以运行bin 目录下的工具文件,
如: , , 和 ;
(2) classpath 是让Java 虚拟机找到所需要的类库;
(3)“E:j2sdk1.4.2_01”与本人安装Java 的具体目录而改变;
7、java程序的执行
<1>Java 程序的编译
在DOS 窗口中输入:Javac
功能:将文本文件 编译成可执行的 字节码文件
<2>运行Java 程序
在DOS 窗口中输入:Java Hello[.class]
第二章 java程序的基本结构
1、一个简单的java小程序的说明
public class HelloWorldApp{
public static void main(String[] args){
}
,println(“hello world!”);
}
1). 关键字public是类的访问修饰符,class是用来创建类的
2).main( )方法有且只有一个,且严格按照格式定义;
3).String args[]是传递给main( )方法的参数,名为args,它是类string 的一个实例,参数
可以没有,可以一个或多个,每个参数用“类名 参数”来指定,多个参数间用逗号分隔;
4).Java 区分大小写;
5).一定以公共类名相同的主文件名 存盘,且大小写一致;
2、Java语言中的注释
(1)// 注释一行
以“//”开始,终止于行尾,一般作单行注释,可放在语句的后面
(2)/*„„*/ 一行或多行注释
以“/*”开始,最后以“*/”结束,中间可写多行。
(3)/**„„*/
以“/**”开始,最后以“*/”结束,中间可写多行。这种注释主要是为支持JDK 工具javadoc而采用的。
3、数据类型
一、 Java 要求在程序中使用任何变量之前必须先声明其类型。
Java 的数据类型分为:
1> 基本类型:整型、浮点型、布尔型、字符型
2> 数组类型:一维数组和多维数组
3> 复合类型:类、接口
二、基本数据类型
类型 位长/b 默认值 取值范围
布尔型 (boolean) 1 false true false
字节型(byte ) 8 0 -128~127
字符型 (char) 16 ‘u0000’ ‘u0000’~’uffff’即0~65535
短整型(short) 16 0 -32768~32767
整型(int) 32 0 -231~231-1
长整型(long) 64 0 -263~263-1
单精度(float) 32 0.0 +-1.4E-45 或+-3.4028235E+38
双精度(double) 64 0.0 +-4.9E-324 或+-1.797693134862315E+308
说明:
(1)一般情况下,没小数点的数字是int 型,有小数点的数是double 型;
(2)String(字符串)型,如:“合肥”、“I am student” ;
(3)Java 的char 类型采用UniCode(国际编码标准)的新字符处理方式,即大字符编码方
案,汉字和字母均看作是一个字符,占两个字节;
(4)Java 程序是定义的变量若没有赋初值,Java 取默认值。
4、变量与常量
常量和变量是java语言中的基本元素。常量一般用于表示一个,而变量则是程序中的基本存储单位。
一、 变量
Java 通常用小写字母或单词作为变量名。变量具有名字、类型、值三元素
1.变量的声明
格式:类型 变量名[,变量名]=初值,„ ;
赋值:[类型] 变量名=值
如:int a=5 , b=6 , c , d ;
说明:
(1)变量名必须在作用域中是唯一的,不同作用域中才允许相同名字的变量出现;
(2)只要在同一代码块没有同名的变量名,可以在程序中任何地方定义变量,一个代码块就是两个相对的“{ }”之间部分。
2.变量的使用范围
每个变量的使用范围只在定义它的代码块中,包括这个代码块中包含的代码块。
在类开始处声明的变量是成员变量,作用范围在整个类;
在方法和块中声明的变量是局部变量,作用范围到它的“}”;
3.变量类型的转换
Java 可以将低精度的数字赋值给高精度的数字型变量,反之则需要强制类型转换。
强制转换格式:(数据类型)数据表达式
字节型 短整型 字符型 整型 长整型 单精度实型 双精度实型
转化规律:由低到高
二、常量
Java中的常量值是用文字串表示的,它区分为不同的类型,如整型常量123,实型常1.23,
字符常量‘a’,布尔常量true、false以及字符串常量“This is a constant string”。
Java 的常量用final 说明,约定常量名一般全部使用大写字母,如果是多个单词组合在一起的,单词之间用下划线连接,常量在程序执行时不可更改。
如:final int i=1;
i=i+1; //错,i 是final(常量),不可更改值
例如:final double IP = 3.14159 D
说明:默认类型为64 位double 双精度类型(D 或d),数字后面加F 或f 则是32 位float 单
精度(实数)类型
5、 运算符
一、赋值运算符
赋值运算符用于把一个数赋予一个变量。赋值运算符两边的类型不一致时,那么如果左侧的数据类型的级别高,则右边的数据将转换成左边的数据类型在赋予左边的变量,否则需要强制类型转换。
赋值运算符包括= 、+=、-=、*=、%=、/=等。
二、算术运算符
算数运算符用于对整型数或者浮点数进行运算,java语言中的算术运算符包括二元运算符和一元运算符。所谓的几元运算符即参加运算的操作数的个数。
1) 二元运算符
Java的二元运算符有+(加)、-(减)、*(乘)、/(除)、%(取余数)。
2) 一元运算符
Java的一元运算符有++(自加)、--(自减)
三、关系运算符
关系运算符用来比较两个值,返回布尔类型的值true或false。
等于 不等于 小于 小于等于 大于等于 大于
== != < <= >= >
四、条件运算符
条件运算符的作用是根据表达式的真假决定变量的值。
1> 格式:条件表达式 ? 表达式2 :表达式3
2> 功能:条件表达式为true,取“表达式2”值,为false,取“表达式3”的值
例: int a=0x10 , b=010 , max ;
max=a>b ? a : b ;
n(max) ; // 输出16
五、 逻辑运算符
第三章 java程序的控制语句
1、java控制语句的分类
1)分支语句:if-el—else 、 switch
2)循环语句:while、do —while、for
2、条件语句
一、 if 语句
格式: if (条件表达式)
语句
功能:条件表达式为true 就执行语句,如果要执行的语句不只是一条是要用大括号将这些语句括起来,而这些语句叫做语句块。
二、if„„else 语句
格式: if (条件表达式)
语句1
else
语句2
功能:条件表达式为true 就执行语句1,为false 执行语句2
三、if„„else 复合结构
格式: if(条件表达式1) 语句1
else if (条件表达式2) 语句2
„„„„
else if (条件表达式n) 语句n
else 语句 n+1
功能:如果某个条件表达式的值为true,就执行它后面的语句,其余部分被忽略,若条件表
达式都为假,执行else 后语句。
3、循环语句
while循环、do—while循环、for循环
一、 while 循环语句
格式:while (条件表达式)
循环语句块
功能:先计算条件表达式,为true,则执行循环语句块,为false 则跳出循环。
二、 do„while 循环语句
格式: do { 循环体 }
while(条件表达式) ;
注意:while 后面的“;”
三、 for循环语句
格式: for(赋初值;判断条件;循环控制变量增减方式)
{ 语句块 }
功能:(1)第一次进入for 循环时,对循环控制变量赋初值;
(2) 根据判断条件检查是否要继续执行循环。为真执行循环体内语句块,为假则结束循环;
(3)执行完循环体内语句后,系统根据“循环控制变量增减方式”改变控制变量值,再回
(3) 到步骤(2)根据判断条件检查是否要继续执行循环。
4、中断控制语句
Java 支持3 种跳转语句:break , continue , return
一、break 语句
格式:break ;
功能:(1)退出switch 结构;
(2)退出当前一层循环。
带标号的break 语句
格式:标识符: //标识符应在break 前面
„„
break 标识符 ;
功能:直接跳转到标识符处,可以退出多重循环;
二、continue 语句
格式:continue ;
功能:只有用在循环结构中,跳过循环体中尚未执行的语句,重新开始下一轮循环。从循环
体第一个语句开始执行。
带标号的continue 语句
格式:标识符:
„„
continue 标识符;
功能:用标号标出想跳到的语句,继续重复执行程序。
说明:“break 标识符;”是结束循环;“continue 标识符;”是继续循环。
三、return 语句
格式:return [表达式] ;
功能:返回调用的语句,执行它的下一条语句,可以带参数返回。
说明:当方法用void 声明时,说明不需要返回值(即返回类型为空),使用不带参数return
语句。不带参数return 语句可以省略。
5、多分支选择语句
格式:switch (表达式) {
case 常量1:[语句块1;] [break;]
„„„„
case 常量n : [语句块n;] [break;]
[default: 语句块n+1;]
}
功能:先计算switch 表达式,再与每个case 常量表达式值相比较,若相同,则执行相应语
句被执行。若都不同,则执行default 语句n+1(若有的话)
说明:
1.switch 后表达式必须是整型,字符型;
2.每个case 的常量必须不同;
3.若没有break,程序将继续执行下一个case 语句;
4.default 位置可任意,但要注意break
第四章 java字符串操作与位运算
1、数制及数制的转换
一、数制
数制是人们利用符号进行计数的科学方法。数制有很多种,在计算机中常用的数制有:十进制,二进制和十六进制。
数制也称计数制,是指用一组固定的符号和统一的规则来表示数值的方法。计算机是信息处理的工具,任何信息必须转换成二进制形式数据后才能由计算机进行处理,存储和传输。
编辑本段
1)十进制数(Decimal)
人们通常使用的是十进制。它的特点有两个:有0,1,2„.9十个基本数字组成,十进制数运算是按“逢十进一”的规则进行的.
在计算机中,除了十进制数外,经常使用的数制还有二进制数和十六进制数.在运算中它们分别遵循的是逢二进一和逢十六进一的法则.
编辑本段
2)二进制数(Binary)
二进制数有两个特点:它由两个基本数字0,1组成,二进制数运算规律是逢二进一。
为区别于其它进制数,二进制数的书写通常在数的右下方注上基数2,或加后面加B表示。
例如:二进制数10110011可以写成(10110011)2,或写成10110011B,对于十进制数可以不加注.计算机中的数据均采用二进制数表示,这是因为二进制数具有以下特点:
(1) 二进制数中只有两个字符0和1,表示具有两个不同稳定状态的元器件。例如,电路中有,无电流,有电流用1表示,无电流用0表示。类似的还比如电路中电压的高,低,晶体管的导通和截止等。
(2) 二进制数运算简单,大大简化了计算中运算部件的结构。
二进制数的加法和乘法运算如下:
0+0=0 0+1=1+0=1 1+1=10
0×0=0 0×1=1×0=0 1×1=1
3)八进制数(Octal)
由于二进制数据的基R较小,所以二进制数据的书写和阅读不方便,为此,在小型机中引入了八进制。八进制的基R=8=2^3,有数码0、1、2、3、4、5、6、7,并且每个数码正好对应三位二进制数,所以八进制能很好地反映二进制。八进制用下标8或数据后面加Q表示 例如:二进制数据 ( 11 101 010 . 010 110 100 )2 对应 八进制数据 ( 3 5 2 .
2 6 4 )8或352.264Q.
4)十六进制数(Hex)
由于二进制数在使用中位数太长,不容易记忆,所以又提出了十六进制数
十六进制数有两个基本特点:它由十六个字符0~9以及A,B,C,D,E,F组成(它们分别表示十进制数10~15),十六进制数运算规律是逢十六进一,即基R=16=2^4,通常在表示时用尾部标志H或下标16以示区别。
例如:十六进制数4AC8可写成(4AC8)16,或写成4AC8H。
二、 数制转换
1) 十---->二
比如:6,如果将它转换成二进制数呢?
10进制数转换成二进制数,这是一个连续除2的过程:
把要转换的数,除以2,得到商和余数,
将商继续除以2,直到商为0。最后将所有余数倒序排列,得到数就是转换结果。
听起来有些糊涂?我们结合例子来说明。比如要转换6为二进制数。
“把要转换的数,除以2,得到商和余数”。
那么:
十转二示意图
要转换的数是6, 6 ÷ 2,得到商是3,余数是0。
“将商继续除以2,直到商为0„„”
现在商是3,还不是0,所以继续除以2。
那就: 3 ÷ 2, 得到商是1,余数是1。
“将商继续除以2,直到商为0„„”
现在商是1,还不是0,所以继续除以2。
那就: 1 ÷ 2, 得到商是0,余数是1
“将商继续除以2,直到商为0„„最后将所有余数倒序排列”
好极!现在商已经是0。
我们三次计算依次得到余数分别是:0、1、1,将所有余数倒序排列,那就是:110了!
6转换成二进制,结果是110。
把上面的一段改成用表格来表示,则为:
被除数 计算过程 商 余数
6 6/2 3 0
3 3/2 1 1
1 1/2 0 1
(在计算机中,÷用 / 来表示)
2) 二 ----> 十
二进制数转换为十进制数
二进制数第0位的权值是2的0次方,第1位的权值是2的1次方„„
所以,设有一个二进制数:0110 0100,转换为10进制为:
下面是竖式:
0110 0100 换算成 十进制
备注:" ^ " 为次方
第0位 0 * 2^0 = 0
第1位 0 * 2^1 = 0
第2位 1 * 2^2 = 4
第3位 0 * 2^3 = 0
第4位 0 * 2^4 = 0
第5位 1 * 2^5 = 32
第6位 1 * 2^6 = 64
第7位 0 * 2^7 = 0 +
---------------------------
100
0乘以多少都是0,所以我们也可以直接跳过值为0的位
3. 十 ----> 八
10进制数转换成8进制的方法,和转换为2进制的方法类似,唯一变化:除数由2变成8。
来看一个例子,如何将十进制数120转换成八进制数。
用表格表示:
被除数 计算过程 商 余数
120 120/8 15 0
15 15/8 1 7
1 1/8 0 1
120转换为8进制,结果为:170。
4)八 ----> 十
八进制就是逢8进1。
八进制数采用 0~7这八数来表达一个数。
八进制数第0位的权值为8的0次方,第1位权值为8的1次方,第2位权值为8的2次方„„
所以,设有一个八进制数:1507,转换为十进制为:
用竖式表示:
1507换算成十进制。
第0位 7 * 8^0 = 7
第1位 0 * 8^1 = 0
第2位 5 * 8^2 = 320
第3位 1 * 8^3 = 512
--------------------------
839
同样,我们也可以用横式直接计算:
7 * 8^0 + 0 * 8^1 + 5 * 8^2 + 1 * 8^3 = 839
结果是,八进制数 1507 转换成十进制数为 839
5) 十 ----> 十六
10进制数转换成16进制的方法,和转换为2进制的方法类似,唯一变化:除数由2变成16。
同样是120,转换成16进制则为:
被除数 计算过程 商 余数
120 120/16 7 8
7 7/16 0 7
120转换为16进制,结果为:78。
6) 十六----> 十
16进制就是逢16进1,但我们只有0~9这十个数字,所以我们用A,B,C,D,E,F这五个字母来分别表示10,11,12,13,14,15。字母不区分大小写。
十六进制数的第0位的权值为16的0次方,第1位的权值为16的1次方,第2位的权值为16的2次方„„
所以,在第N(N从0开始)位上,如果是是数 X (X 大于等于0,并且X小于等于 15,即:F)表示的大小为 X * 16的N次方。
假设有一个十六进数 2AF5, 那么如何换算成10进制呢?
用竖式计算:
2AF5换算成10进制:
第0位: 5 * 16^0 = 5
第1位: F * 16^1 = 240
第2位: A * 16^2 = 2560
第3位: 2 * 16^3 = 8192 +
-------------------------------------
10997
(别忘了,在上面的计算中,A表示10,而F表示15)
现在可以看出,所有进制换算成10进制,关键在于各自的权值不同。
假设有人问你,十进数 1234 为什么是 一千二百三十四?你尽可以给他这么一个算式:
1234 = 1 * 10^3 + 2 * 10^2 + 3 * 10^1 + 4 * 10^0
7) 二 ----> 八
(11001.101)(二)
整数部分: 从后往前每三位一组,缺位处用0填补,然后按十进制方法进行转化, 则有:
001=1
011=3
然后我们将结果按从下往上的顺序书写就是:31,那么这个31就是二进制11001的八进制形式
小数部分: 从前往后每三位一组,缺位处用0填补,然后按十进制方法进行转化, 则有:
101=5
然后我们将结果部分按从上往下的顺序书写就是:5,那么这个5就是二进制0.101的八进制形式
所以:(11001.101)(二)=(31.5)(八)
8) 八 ----> 二
(31.5)(八)
整数部分:从后往前每一位按十进制转化方式转化为三位二进制数,缺位处用0补充 则有:
1---->1---->001
3---->11
然后我们将结果按从下往上的顺序书写就是:11001,那么这个11001就是八进制31的二进制形式
说明,关于十进制的转化方式我这里就不再说了,上一篇文章我已经讲解了!
小数部分:从前往后每一位按十进制转化方式转化为三位二进制数,缺位处用0补充 则有:
5---->101
然后我们将结果按从下往上的顺序书写就是:101,那么这个101就是八进制5的二进制形式
所以:(31.5)(八)=(11001.101)(二)
9) 十六 ----> 二 ;二 ----> 十六
二进制和十六进制的互相转换比较重要。不过这二者的转换却不用计算,每个C,C++程序员都能做到看见二进制数,直接就能转换为十六进制数,反之亦然。
我们也一样,只要学完这一小节,就能做到。
首先我们来看一个二进制数:1111,它是多少呢?
你可能还要这样计算:1 * 2^0 + 1 * 2^1 + 1 * 2^2 + 1 * 2^3 = 1 * 1 + 1 * 2 + 1
* 4 + 1 * 8 = 15。
然而,由于1111才4位,所以我们必须直接记住它每一位的权值,并且是从高位往低位记,:8、4、2、1。即,最高位的权值为2^3 = 8,然后依次是 2^2 = 4,2^1=2, 2^0 =
1。
记住8421,对于任意一个4位的二进制数,我们都可以很快算出它对应的10进制值。
下面列出四位二进制数 xxxx 所有可能的值(中间略过部分)
仅4位的2进制数 快速计算方法 十进制值 十六进值
1111 = 8 + 4 + 2 + 1 = 15 F
1110 = 8 + 4 + 2 + 0 = 14 E
1101 = 8 + 4 + 0 + 1 = 13 D
1100 = 8 + 4 + 0 + 0 = 12 C
1011 = 8 + 0 + 2+ 1 = 11 B
1010 = 8 + 0 + 2 + 0 = 10 A
1001 = 8 + 0 + 0 + 1 = 9 9
....
0001 = 0 + 0 + 0 + 1 = 1 1
0000 = 0 + 0 + 0 + 0 = 0 0
二进制数要转换为十六进制,就是以4位一段,分别转换为十六进制。
如(上行为二制数,下面为对应的十六进制):
1111 1101 , 1010 0101 , 1001 1011
F D , A 5 , 9 B
反过来,当我们看到 FD时,如何迅速将它转换为二进制数呢?
先转换F:
看到F,我们需知道它是15(可能你还不熟悉A~F这五个数),然后15如何用8421凑呢?应该是8 + 4 + 2 + 1,所以四位全为1 :1111。
接着转换 D:
看到D,知道它是13,13如何用8421凑呢?应该是:8 + 4 + 1,即:1101。
所以,FD转换为二进制数,为: 1111 1011
由于十六进制转换成二进制相当直接,所以,我们需要将一个十进制数转换成2进制数时,也可以先转换成16进制,然后再转换成2进制。
比如,十进制数 1234转换成二制数,如果要一直除以2,直接得到2进制数,需要计算较多次数。所以我们可以先除以16,得到16进制数:
被除数 计算过程 商 余数
1234 1234/16 77 2
77 77/16 4 13 (D)
4 4/16 0 4
结果16进制为: 0x4D2
然后我们可直接写出0x4D2的二进制形式: 0100 1101 0010。
其中对映关系为:
0100 -- 4
1101 -- D
0010 -- 2
同样,如果一个二进制数很长,我们需要将它转换成10进制数时,除了前面学过的方法是,我们还可以先将这个二进制转换成16进制,然后再转换为10进制。
下面举例一个int类型的二进制数:
01101101 11100101 10101111 00011011
我们按四位一组转换为16进制: 6D E5 AF 1B
2、补码
所有的整数类型(除了char 类型之外)都是有符号的整数。这意味着他们既能表示正数,又能表示负数。 Java使用补码来表示二进制数 ,在补码表示中 ,最高位为符号位 ,正数的符号位为0,负数为1。补码的规定如下 :
对正数来说 ,最高位为0,其余各位代表数值本身(以二进制表示),如 +42的补码 为
00101010。
对负数而言 ,把该数绝对值的补码按位取反 ,然后对整个数加 1,即得该数的补码 。
如-42的补码为11010110(00101010按位取反11010101 +1=11010110 )
用补码来表示数 ,0的补码是唯一的 ,都为00000000。 (而在原码 ,反码表示中,+0和-0的表
示是不唯一的,可参见相应的书籍 )。而且可以用 111111表示-1的补码(这也是补码与原码
和反码的区别)。
先把负数写为其补码形式(在此不议),然后再根据二进制转换其它进制的方法进行。
如-12的补码
第一步:转换成二进制
1000 0000 0000 1100
第二步:补码,取反加一
注意:取反时符号位不变!
1111 1111 1111 0100
3、位运算符
位运算符用来对二进制位进行操作 ,Java中提供了如下所示的位运算符 :
位运算符(>>,<<,>>>,&,|,^,~) ,位运算符中 ,除~ 以外,其余均为二元运算符 。
操作数只能为整型和字符型数据 。
Java 位运算符
Java 定义的位运算(bitwise operators )直接对整数类型的位进行操作,这些整数类型包括long,int,hort,char,and byte 。表4-2 列出了位运算:
运算符 结果
~ 按位非(NOT)(一元运算)
& 按位与(AND)
| 按位或(OR)
^ 按位异或(XOR)
>> 右移
>>> 右移,左边空出的位以0填充 ;无符号右移
<< 左移
&= 按位与赋值
|= 按位或赋值
^= 按位异或赋值
>>= 右移赋值
>>>= 右移赋值,左边空出的位以0填充 ;无符号左移
<<= 左移赋值
按位非(NOT)
按位非也叫做补,一元运算符NOT“~”是对其运算数的每一位取反。例如,数字42,它的二进制代码为: 00101010
经过按位非运算成为 11010101
按位与(AND)
按位与运算符“&”,如果两个运算数都是1,则结果为1。其他情况下,结果均为零。看下面的例子: 00101010 42 &00001111 15
00001010 10
按位或(OR)
按位或运算符“|”,任何一个运算数为1,则结果为1。如下面的例子所示:
00101010 42 | 00001111 15
00101111 47
按位异或(XOR)
按 位异或运算符“^”,只有在两个比较的位不同时其结果是 1。否则,结果是零。下面的例子显示了“^”运算符的效果。这个例子也表明了XOR 运算符的一个有用的属性。注
4、数组
数组是有序数据的集合,数组中的每个元素具有相同的数组名,根据数组名和下标来唯一确定数组中的元素。使用时要先声明后创建
一、一位数组
1) 一维数组的声明
格式: 数据类型 数组名[ ] 或 数据类型 [ ]数组名
例: int a[] ; String s[] ; char []c ;
说明:定义数组,并不为数据元素分配内存,因此“[ ]”中不用指出数组中元素个数。
2 )一维数组的创建与赋值
创建数组并不是定义数组,而是在数组定义后,为数组分配存储空间,同时对数组元素进行初始化
(1)用运算符new 分配内存再赋值
格式:数组名=new 数据类型[size]
例:int a[] ;
a=new int[3] ; // 产生a[0] , a[1] , a[2] 三个元素
a[0]=8 ; a[1]=8 ; a[2]=8 ;
3)直接赋初值并定义数组的大小
例:int i[]={4,5,010,7,3,2,9} ;
String names[]={“张三”,”李四”,”王五”,”宋七”} ;
4)测试数组长度(补充)
格式:数组名.length
char c[]={‘a’,’b’,’c’,’北’,’京’} ;
() ; // 输出5
二、多维数组
以二维数组为例
例:int d[][] ; // 定义一个二维数组
d=new int[3][4] ; // 分配3 行4 列数组内存
int a[][]=new int[2][] ;
a[0]=new int[3] ; // 第二维第一个元素指向3 个整型数
a[1]=new int[5] ; // 第二维第一个元素指向5 个整型数
注意:Java 可以第二维不等长
int i[][]={{0},{1,4,5},{75,6},{8,50,4,7}} ; //定义和赋初值在一起
下面数组定义正吴的判断
int a[][]=new int[10,10] //错
int a[10][10]=new int[][] //错
int a[][]=new int[10][10] //错
int []a[]=new int[10][10] //对
int [][]a=new int[10][10] //对
注意:java中二维数组分配空间是第二维可以为空,但是第一维必须分配内存。
5、字符串
字符串的几种用法:
拼接 直接用“+”把两个字符串拼接起来
例如:String firstName = “li”;
String secondName = “ming”;
String fullName = firstName+secondName;
检测字符串是否相等 检测两个字符串内容是否相等时使用“equals”;比较两个字符串的引用是否相等时用“==”
得到字符串的长度 字符串变量名.length();
第五章 类的构建和对象的使用
1、面向对象简介
1)对象:对象包括对象特征(行为)和对象属性
2)面向对象的步骤:
<1>写类找类(系统提供或是第三方软件)
<2>用类创建对象
<3>把对象组合成一个更大的对象,从而形成一个系统
<4>通过对象之间的消息传递来完成任务
3) 面向对象的思想:将客观事物看作具有状态和行为的对象,通过抽象找出同一类对象的
共同状态和行为构成一个类
4) 面向对象的特点:继承性、封装性、多态性
继承性:支持继承通过接口实现多继承
封装性: 封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。
多态性:从另一个角度将接口从具体的实施细节中分离出来
2、java中的类
类是java的核心和本质,用java编写的任何东西都在类中,java就是很多类的组合。
类类之间的3种关系:依赖关系(uses-a)、聚集关系(has-a)、继承关系(is-a)
1) 类的定义:用class来创建类
格式: [修饰符]
{ 类体(成员变量和成员方法) }
修饰符:指明类在使用时所受到的限制,包括类访问权限[public]和其他特性[abstract],[final]
说明:
<1>class <类名> 告诉编译器这是一个类
<2>Public(公共的)
在没有任何修饰符的默认情况下,类只能被同一个源程序文件或同一个包中的其他类使用,加上public 后,该类可以被任何包中的类使用,称为公共类。
注意:
在同一个源程序文件中不能出现两个及以上的public 类,否则编译器会告诉你将第二
个public 类放在另一个文件中。
2)对象的声明与创建
类的对象的模板,Java 运行应该是用类创建实例化对象。一旦任务完成,对象就会被垃圾收集器收回,完成它从创建、使用到清除。
<1>创建对象与构造方法
创建对象格式: 类名 对象名=new 类名([参数]) ;
说明:(1)运算符new 为对象分配内存空间;
(2)生成对象的最后一步是执行构造方法;
(3)创建对象相当于定义一个变量,即分两步进行。
创建对象分成两步: 类名 对象名 ;
对象名=new 类名([参数]) ;
<2>对象初始化的说明
(1)系统如何对变量初始化
当用new 创建了一个对象时,系统会为对象中的变量进行初始化。即不但为变量分配相应的存储单元,还设置相应初值。系统为byte , short , int , long 类型设置初值为0;float 类型变量初值为0.0f;double 类型变量初值为0.0;char 字符型变量为’u0000’;boolean 逻辑变量初值为false;引用类型初值勤为null。
(2)构造方法的作用与构成
new 操作符为对象分配内存后将调用类的构造方法确定对象的初始状态,初始化所有变量。构造方法功能:创建对象时,用给定的值,将对象初始化
<3>对象的使用
格式:<对象名>.<变量名>
<对象名>.<方法名([参数])>
3、方法
一、方法名
要以是任何有效的Java 标识符,方法名可以和成员变量同名,也可以和成员方法同
名。同一个类中的方法同名现象在OOP 中称为方法重载(overload)。
二、参数表
方法的调用者正是通过参数表将外部消息传递给方法的。在参数表中要声明参数的类型,并用逗号分隔多个参数。
三、方法体
方法体包含在一对大括号中,即使方法体中没有语句,一对大括号也是必不可少的。
四、 消息传递
一个对象和外部交换信息主要靠方法的参数来传递,如果允许的话,外部对象也可以直接存取一个对象的成员变量。
在Java 中调用方法时,如果传递的参数是基本数据类型,在方法中将不能改变参数的值,你只能使用它们。如果传递的是对象引用,你也不能在方法中修改这个引用,但可以调用对象的方法以及修改允许存取的成员变量。所以想改变参数的值,可采用传递对象的方法,间接修改参数的值。
五、方法的重载
重载:在同一个类中,有两个或是两个以上的相同名字的方法,只要他们的参数声明不同即可。参数不同可以是数量不同,类型不同,或两者都不同,或是顺序不同,但重载方法必须有相同的方法名,返回类型不作为重载的标准。
4、构造方法和初始化对象
一、构造方法特点:
(1)构造方法名与类名相同,且不指定类型说明;
(2)可以重载,即可以定义多个参数个数不同的函数,系统可以根据参数的不同,自动调
用正确的构造方法;
(3)程序中不能直接调用构造函数,在创建对象时系统自动;
(4)可以不设计构造方法,若在初始化时还要执行一些其他命令,就必须设计构造方法,
因为Java 规定命令语句不能出现在类体中,只能放在方法中。
二、 This关键字
This的含义:本身代表当前的对象引用。
必须使用this的两种情况:
1) 当类中有两个同名变量,一个是类的成员变量,另一个是方法中的局部变量,使用this区分成员变量和局部变量。
2) 当在一个构造方法中调用另一个构造方法时用this(),如果被调用的构造方法时代参数的,this在调用时也要带上参数。
第六章 类的继承
1、类的继承
继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。
super关键字
java中通过super来实现对父类成员的访问,super用来引用当前对象的父类。Super 的使用有三种情况:
1)访问父类被隐藏的成员变量,如:
super. 变量;
2)调用父类中被重写的方法,如:
super.成员函数据名(实参)
3)调用父类的构造函数(当父类不能提供无参的构造方法时),如:
super(参数1,参数2„)
调用基类中的某一个构造函数(应该为构造函数中的第一条语句);
2、Object类
Java中所有类(包括用户自己定义的类)都自动继承Object类,即Object类是所有类的父类。
3、方法的覆盖(重写)
重写的要求:
子类覆盖方法和父类被覆盖方法的方法返回类型,方法名称,参数列表必须相同
子类覆盖方法的访问权限必须大于等于父类的方法的访问权限
方法覆盖只能存在于子类和父类之间
子类覆盖方法不能比父类被覆盖方法抛出更多异常
4、final关键字在继承中的使用
final可以用于以下四个地方:
1) 定义变量,包括静态的和非静态的。
如果final修饰的是一个基本类型,就表示这个变量被赋予的值是不可变的,即它是个常量;如果final修饰的是一个对象,就表示这个变量被赋予的引用是不可变的,不可改变的只是这个变量所保存的引用,并不是这个引用所指向的对象,其实更贴切的表述final的含义的描述,那就是,如果一个变量或方法参数被final修饰,就表示它只能被赋值一次,但是JAVA虚拟机为变量设定的默认值不记作一次赋值。
被final修饰的变量必须被初始化。初始化的方式有以下几种:
1. 在定义的时候初始化。
2. 在初始化块中初始化。
3. 在类的构造器中初始化。
4. 静态变量也可以在静态初始化块中初始化。
2) 定义方法。
当final用来定义一个方法时,它表示这个方法不可以被子类重写,但是它这不影响它被子类继承。
说明:
具有private访问权限的方法也可以增加final修饰,但是由于子类无法继承private方法,因此也无法重写它。编译器在处理private方法时,是按照final方法来对待的,这样可以提高该方法被调用时的效率。不过子类仍然可以定义同父类中的private方法具有同样结构的方法,但是这并不会产生重写的效果,而且它们之间也不存在必然联系。
3)定义类。
由于final类不允许被继承,编译器在处理时把它的所有方法都当作final的,因此final类比普通类拥有更高的效率。final的类的所有方法都不能被重写,但这并不表示final的类的属性(变量)值也是不可改变的,要想做到final类的属性值不可改变,必须给它增加final修饰。
第七章 类的高级特性
1、 Static关键字
在Java语言中,static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念。
被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。
用public修饰的static成员变量和成员方法本质是全局变量和全局方法,当声明它类的对象时,不生成static变量的副本,而是类的所有实例共享同一个static变量。
static变量前可以有private修饰,表示这个变量可以在类的静态代码块中,或者类的其他静态成员方法中使用(当然也可以在非静态成员方法中使用),但是不能在其他类中通过类名来直接引用,这一点很重要。实际上你需要搞明白,private是访问权限限定,static表示不要实例化就可以使用,这样就容易理解多了。static前面加上其它访问权限关键字的效果也以此类推。
static修饰的成员变量和成员方法习惯上称为静态变量和静态方法,可以直接通过类名来访问,访问语法为:
类名.静态方法名(参数列表...)
类名.静态变量名
用static修饰的代码块表示静态代码块,当Java虚拟机(JVM)加载类时,就会执行该代码块(用处非常大)。
static在Java语言中的使用有四种:(变量、方法、代码块、内部类)
一、static变量
按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类
变量;另一种是没有被static修饰的变量,叫实例变量。
两者的区别是:
对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过
程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。
对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。
二、静态方法
静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。因为实例成员与特定的对象关联!这个需要去理解,想明白其中的道理,不是记忆!!!
因为static方法独立于任何实例,因此static方法必须被实现,而不能是抽象的abstract。
3、static代码块
static代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。
利用静态代码块可以对一些static变量进行赋值,最后再看一眼这些例子,都一个static的main方法,这样JVM在运行main方法的时候可以直接调用而不用创建实例。
4. 静态内部类(Inner Class)
为正确理解static在应用于内部类时的含义,必须记住内部类的对象默认持有创建它的那个封装类的一个对象的句柄。然而,假如我们说一个内部类是static的,这种说法却是不成立的。
static内部类意味着:
(1) 为创建一个static内部类的对象,我们不需要一个外部类对象。
(2) 不能从static内部类的一个对象中访问一个外部类对象。
说明:
1)但在存在一些限制:由于static成员只能位于一个类的外部级别,所以内部类不可拥有static数据或static内部类。
2)倘若为了创建内部类的对象而不需要创建外部类的一个对象,那么可将所有东西都设为static。为了能正常工作,同时也必须将内部类设为static。如下所示:
在main()中,我们不需要Parcel10的对象;相反,我们用常规的语法来选择一个static成员,以便调用将句柄返回Contents和Destination的方法。
3)通常,我们不在一个接口里设置任何代码,但static内部类可以成为接口的一部分。由于类是“静态”的,所以它不会违反接口的规则——static内部类只位于接口的命名空间内部:这样便生成一个独立的、名为TestBed$Tester的类(为运行程序,请使用“java
TestBed$Tester”命令)。可将这个类用于测试,但不需在自己的最终发行版本中包含它。
2、 高级访问修饰符
private:私用 只能在被类中被访问
default:默认 只能被同一个包中的类访问
protected:受保护的 只能被同一个包中的类和不同包中的子类访问
public:公有 可以被任何类访问
3、 封装类
1).基本类型只能按值传递,而每个基本类型对应的封装类是按引用传递的,是通过private实现的。
2)从性能上说java中的基本类型是在堆栈上创建的,而所有的对象类型都是在堆上创建的,(对象的引用在堆栈上创建)。比如
Integer i=new Integer(10); 其中new Integer()是在堆上创建的,而他的引用Integer i是在堆栈上。 封装类的出现,是为了更方便的使用一些基本类型不具备的方法,比如valueOf(),toString()等等。还有你如果想传递一个int对象的引用,而不是值,那只能用封装类。在堆栈上分配内存的调用效率和在堆上分配内存的效率差太多了。虽然在堆栈上分配内存效率高,不过在堆栈上分配内存有内存泄露的问题。(这是一个平庸程序员基本解决不了的问题...)java用了一种很天才的方法提高了在堆上分配内存的效率,尽管如此,java还是慢。他不太可能达到向c++那么快,尽管他一直在承诺总有一天虚拟机会和机器码速度一样快。
4、内部类
内部类是嵌套定义于另一个类内部的类。
(1)内部类可以由abstract,private或者protected定义。
(2)内部类的类名不可以和它所在的类名相同。
(3)在类中,只有内部类可以被声明为static成员。
第八章 抽象类和接口
1、包
包(package)是类和接口的集合,利用包可以把常用的类或功能相似的类放在一个包中。
Java 还提供了系统包。
包是Java 提供的一种区别类名空间的机制,是类的逻辑组织形式,一个包对应一个文件夹,
包中还可以有包,称为包等级。
当源程序中没有声明类所在的包时,Java 将类放在默认包中,即运行编译器的当前文件夹中。这时不能出现重复的类名。
一、Java 的系统包
Java 提供了大量的类,为便于管理和使用,分为不同的包。这些包又称类库或API 包,所谓API(application program interface)即应用程序接口。API 包一方面提供丰富的类与方法供大家使用,如画图形、播放声音等,另一方面又负责和系统软硬件打交道,把用户程序的功能圆满实现。许多Java API 包都以“java.”开头,以区别用户创建的包。
二、包的引用
1)导入包语句
格式:import <包名1>[.<包名2>„„] .<类名>|* ;
说明:如果有多个包或类,用“.”分割,“*”表示包中所有的类。
例: import // 导入 包中的Applet 类
import .* // 导入 包中的所有类
包是系统自动隐含导入
2)包的路径
由于Java 使用文件系统来存储包和类,类名就是文件名,包名就是文件夹名,设置环境变量用classpath 方法。
三、 声明自定义包
1)创建自定义包
格式: package <包名>
说明:(1)声明包语句必须添加在源程序的第一行,表示该文件的全部类都属于这个包
(2)可以在不同的文件中使用相同的声明语句,可将不同文件中的类都包含在相同的包中。
(3)若在程序中没有声明包,类就放在默认的包中,这个包没有名字,默认包适用于小的程序。
2)设置包的路径
用自定义包名建立一个文件夹,如:c: Mypackage
设置路径:set classpath=. ; c:j2sdk1.4.2 ; c:mypackage
以后其它类使用自定义包里的类用命令:import Mypackage.*
3)创建包等级
格式: package <包名1>[.<包名2>][.<包名3>][.<„„>]
2、抽象类
抽象类实际上,抽象类就是比普通类多了一个抽象方法而已。
(1) 抽象类是包含抽象方法的类称为抽象类,抽象方法是只声明而未实现的方法,抽象类可必须有抽象方法,可包含具体方法。
(2)所有的抽象方法和抽象类都必须使用abstract关键字进行声明。
(3)抽象类不能直接进行实例化操作,但可以声明,其目的在于扩展,不能用构造方法对数据成员进行初始化。
(4)抽象类继承的时候可以不必实现父类的所有抽象方法,但第一个具体子类必须实现抽象类的全部方法。
抽象方法只有方法定义,没有方法体。如果一个类包含任何抽象方法,包括直接的和继承所得,则这个类必须是抽象的。如果一个类是抽象的,则不能创建此类的对象,抽象类强制要求他的所有子类重写自己的方法以覆盖抽象方法。
如果某个字累没有覆盖抽象方法,则这个字类也要成为抽象类,即必须被声明成abstract类。
(5)抽象类不能含final关键字。
(6)抽象类中允许有构造方法,但构造方法是不能直接调用的,是交给子类调用的,子类对象的实例化,永远先调用父类的构造函数,抽象类中的属性要初始化,则肯定还是依赖构造方法的。
(7)抽象类的方法必须由具体子类实现,所以抽象方法不能是private类型,另外abstact和sychronied不能混用。
3、接口
接口(interface)解决了Java 不支持多重继承的问题,可以通过实现多个接口达到与多重继承相同的功能。
Java 语言不支持多重继承,为了实现多重继承的功能,Java 提供接口来实现,且比多重继承具有更强的功能。多重继承指一个类可以是多个类的子类接口可以看作是没有实现的方法和常量的集合。接口与抽象类相似,接口中的方法只是做了声明,而没有定义任何具体的操作方法。
接口功能:
(1)通过接口可以实现不相关类的相同行为,而不需要考虑这些类之间的层次关系
(2)通过接口可以指明多个类需要实现的方法
(3)通过接口可以了解对象的交互界面,而不需了解对象所对应的类。
一、接口的特点
1)接口中定义的方法没有方法体,它们以参数列表后面的分号作为结束,他本质上是抽象方法;
2)在接口中指定的方法没有默认的实现,每个包含接口的类必须实现所有的方法;
3)即口中可以声明变量,它们一般是final和static类型的,它们必须以常量值初始化;
4)如果借口本身定义成public,所有方法和变量都是public的。
二、实现系统提供的接口
接口中定义的变量全部隐含为了final 和static,表明这些变量不能被实现接口方法的类改变,这些变量还必须设置初值。如果接口为public,则接口中的方法和变量也全部为public,否则只能被处于同一包中的成员访问。类引用接口不叫继承而称为实现。
说明:
在实现接口时,要实现所有接口中定义的所有方法,方法的实现要以具有具体的实现内容,也可以是空的方法,即只有方法名或参数,没有变量、没有具体操作语句。
三、创建自定义接口
格式:[修饰符]
{ 静态常量及方法声明 }
说明:(1)Java 系统会自动把接口中声明的变量当作static final 类型,不管是否使用了这些修饰符,且必须赋初值,这些变量值都不能被修改。
(2)接口中的方法默认为abstract,不管有没有这些修饰符。
(3)接口若是public,那么该接口可被任意类实现,否则只有与接口在同一个包中类的实现。
(4)接口若为public,则接口中的变量也是public。、
四、接口的继承
1)接口的单继承
接口之间的继承与类的继承一样使用extends
格式: interface <新接口名> extends <已有接口名>
如果一个类实现了接口B,那么它必须实现接口A 和接口B 中的全部方法。
2)接口的多重继承
在Java 语言中,不支持类的多重继承,但支持接口的多重继承
格式: interface <新接口名> extends <已有接口名1>[<,接口名2>„]
注意:引用接口时,必须实现接口中的所有方法,否则就将该类也声明成abstract类型的。
4、java中的多态
在一个类中,可以定义多个同名的方法,只要确定它们的参数个数和类型不同,这种现象称为类的多态。类的多态性体现在两方面:一是方法的重载上,包括成员方法和构造方法的重载;二是在继承过程中,方法的重写。
多态性是面向对象的重要特征。
方法重载和方法覆写实际上属于多态性的一种体现,真正的多态性还包括对象多态性的概念。
对象多态性主要是指子类和父类对象的相互转换关系。
(1)向上转型:父类 父类对象=子类实例 ----->自动完成
(2)向下转型:子类 子类对象 =(子类)父类实例 ———>强制完成
从对象多态性的概念看,子类为父类实例化是一个比较容易的操作,因为可以发生自动的向上转型关系,调用的方法永远是被子类覆写过的方法。因此,可以通过对象多态性为抽象类实例化,接口也可以通过对象的多态性完成实例化。
抽象类本身最大的用处在于定义模版操作,而接口最大的作用在于定义标准。
第九章 异常处理和程序调试
1、异常处理
一、异常的对象的根类是Throwable类
1) Throwable类有分成Error类和Excepion类两个分支
Error类表示严重错误
Exception类表示可以在程序中处理的错误
2) Exception类分成运行时异常和非运行时异常(已检查异常)
运行时异常编译不检查,在运行时才会发生异常
已检查异常编译时就会作检查,不处理异常则通不过编译
二、异常的处理
异常处理通过五个关键字控制:try、catch、throw、throws和finally
一、Try—catch语句
格式: try {„„} // 被监视的代码段
catch(异常类型1 e) // 要处理的第一种异常
catch(异常类型2 e) // 可以不写成e
„„„„
finally {„„} //最终处理
对异常进行处理时,一般是把可能会发生异常情况的代码放在try 语句段中,利用try 语句对这组代码进行监视。发果发生了第一种异常,使用第一个catch 中的代码段处理;如果发生了第二种异常,则使用第二个catch 代码段处理。
如果希望在异常发生时能确保有一段代码被执行,那么应该使用finally 子句。
catch 语句在执行前,必须识别抛出的异常对象类型是catch 能够捕获的“异常类”如果catch语句参数中声明的异常类与抛出的异常类相同,或者是它的父类,catch 语句就可以捕获任何这种异常类的对象,e 为相应的异常对象。
二、throw 语句
异常对象可以是Java 系统抛出的。也可以通过代码实现,使用throw 语句就可以明确抛出一个异常。
格式:throw <异常对象>
三、throws 子句
throws 用来表明一个方法可能抛出的各种异常,并说明该方法会抛出但不捕获异常。
1)抛出异常的方法(自学)
2)调用方法处理异常(自学)
3)由方法抛出异常交系统处理
对于程序中需要处理的异常,一般编写try-catch-finally 语句捕获处理,而对于程序中无法处理必须由系统处理的异常,可以使用throws 语句在方法中抛出异常交由系统处理。
格式:返回类型 方法名(参数表) throws 异常类型表
四、finally 语句
每个try 语句至少要有一个与之相匹配的catch 或finally 子句。
finally 子句总是在方法返回前执行。
2、日志的使用
日志的优点:1)监视代码中变量的变化情况。把数据周期性的记录到文件中供其他应用进行统计分析工作;
2)跟踪代码的轨迹,作为日后审计的依据
3)但当集成开发环境的调试器,向文件或是控制台打印代码的调试信息
3、调试器的使用
设置断点:在想要让程序运行到哪条语句停止,就把光标放到该语句所在的那一行上,并从菜单选择Run—Toggle Line BreakPointjike ,也可以点击右键来找到这个选项,此时被设置断点的那一行将被高亮显示。
调试过程:从菜单中选择Run—Debug As—>Java Applation即可。
第十章 第十一章 文件与流的应用
1、java的文件管理
一、File类简介
File类是用来做磁盘管理的,并不是用来存储的,换句话说局势直接处理文件和文件系统的。也就是说,file类没有指定从文件读取或是向文件存储的方式,,它只描述了文件本身的属性。
三、 目录
目录是一个包含其他文件和路径列表的File类。当创建一个File对象且它是目录时,isDirectory()方法返回true。这种情况下可以调用该对象的list()方法来提取该目录内部其他文件和目录的列表。该方法有两种形式:
1) 第一种形式如下:
String[] list()
这种方式返回一个文件列表,该列表示String数组。
2) 第二种形式:
String[] list(FilenameFilter FFObj)
这种方式返回一个特定名称的一组文件
2、流
一、流的定义
所谓流,就是数据的管道。Java程序通过流来完成输入/输出。流失生产和消费的抽象。流通过java的输入输出系统与物理设备链接。
二、流的分类
流分为字节流和字符流两种。字节流用来处理字节的输入和输出,字符流为字符的输入和输出处理提供了方便,字符流比字节流更有效率。
1) 字节流
字节流由两个抽象类定义:InputStream和OutputStream,分别用于输入和输出,所有其他面向数据流的输入输出都要扩展这两个基类。
2) 字符流
字符流也由两个抽象类定义:Reader和Writer,这些抽象类处理统一的编码的字符流,读写以编码方式的Unicode的双字节数据。
注意:要使用流类,必须导入包。
三、标准输入、输入流
Java标准数据流是指在字符方式下(如DOS),程序与系统进行交互的方式,分为三种:
1)
标准输入流,通常此流对应于键盘输入或者有主机环境或用户指定的另一个输入源。
2)
标准输出流,通常此流对应于显示器输出或者由主机环境或者用户指定的另一输出目标。
3)
标准错误输出流,此流已打开并准备接受输出数据。
4、对象序列化
一、对象序列化的定义
所谓对象序列化就是将对象的状态转化成字节流,以后可以通过这些流再生成相同状态的对象。Java序列化比较简单,实现Serializable接口的对象可以转换成字节流或是从字节流恢复,不需要在类中增加任何代码。Serializable是标志性接口,不具有方法。
注意:不是每个类都可以序列化,有些类是不能序列化的,例如涉及线程的类与特定的JVM有非常复杂的关系。
二、对象序列化的用途
对象序列化有两种用途:
(1) java的JavaBeans
Bean的状态信息通常是在设计时配置的,Bean的状态信息必须被存起来,以便当程序运行时回复这些信息,这需要将对象状态保存到文件中,而后能够通过读入对象状态来重新构造对象,恢复程序状态。
(2) RMI
允许对象在本机上一样操作远程机器上的对象;或使用套接字在网络上传送对象的程序来说,这些都算是实现serialization的机制。
5、转换流的使用
用InputStreamReader和OutputStreamWriter来字节流转换成字符流。
第十二章 集合的应用(一)
1、 java中的集合
集合类是放在.*;这个包里。集合类存放的都是对象的引用,而非对象本身,为了说起来方便些,我们称集合中的对象就是指集合中对象的引用(reference)。
一、集合的种类
集合类型主要有3 种:set(集)、list(列表)和map(映射)
(1) Set
集(set)是最简单的一种集合,它的对象不按特定方式排序,只是简
单的把对象加入集合中,就像往口袋里放这个,集合里面一定
(2)List
列表(List)的主要特征是其对象以线性方式存储,没有特定顺序,只
有一个开头和一个结尾,当然,它与根本没有顺序的Set是不同的。它是链
表,一条链肯定有顺序这个顺序就不一定了。
(3)Map
映射(Map),这个在java 里不是地图的意思,其实地图也是映射。它
里面的东西是键-值对(key-value)出现的,键值对是什么呢?举个例子,
比如我们查字典,用部首查字法。目录那个字就是键,这个字的解释就是值。
键和值成对出现。
二、细化集合中的三种类型
(1)集:HashSet 使用HashMap实现
TreeSet 在集中以升序对对象排序的集的实现,使用TreeMap实现。
(2)列表
Vector 实现一个类似数组的表,自动增加容量来容纳你所需的元素,它是线程安全的,是同步的。
Stak 这个类从Vector派生而来,并且增加了方法实现桟一种后进先出的存储机构。
Linked List 实现了一个链表
ArrayList 实现了一个数组,但是线程不安全,不是同步的
(3) 映射
HashTable 实现一个映象,所用的键必须为空。它的线程是安全的,效率比HashMap要慢。
HashMap 实现一个映象,允许存储空对象,而且允许键为空。
WeakHashMap 一般不用
TreeMap 实现这样一个映象,对象是按键升序排列的
2、 list接口
List(接口) 顺序是List 最重要的特性;它可保证元素按照规定的顺序排列。List 为Collection 添加了大量方法,以便我们在List 中部插入和删除元素(只推荐对LinkedList 这样做)。List 也会生成一个ListIterator(列表反复器),利用它可在一个列表里朝两个方向遍历,同时插入和删除位于列表中部的元素(同样地,只建议对LinkedList 这样做)
ArrayList* 由一个数组后推得到的List。作为一个常规用途的对象容器使用,用于替换原先的Vector。允许我们快速访问元素,但在从列表中部插入和删除元素时,速度却嫌稍慢。一般只应该用ListIterator 对一个ArrayList 进行向前和向后遍历,不要用它删除和插入元素;与LinkedList 相比,它的效率要低许多LinkedList 提供优化的顺序访问性能,同时可以高效率地在列表中部进行插入和删除操作。但在进行随机访问时,速度却相当慢,此时应换用ArrayList。也提供了addFirst(),addLast(),getFirst(),getLast(),removeFirst() 以及removeLast()(未在任何接口或基础类中定义),以便将其作为一个规格、队列以及一个双向队列使用。
3、 Map类型的集合
1)Map接口是用来维持很多“键—值”对,以便通过一个键查找相应的值。
2)HashMap基于一个散列表实现,针对“键—值”对的插入和检索,这种形式具有较好的执行性能。
3)TreeMap在一个二叉树的基础上实现。查看键或者“键—值”对是,它们会按固定的顺序排列。TreeMap是含有subMap()方法的唯一一种Map,利用它可以返回树的一部分。
4)WeakHashMap 是一种特殊的HashMap,对于一些弱键,垃圾收集器会自动删除,因而,对应的“键—值”对可能会消失
第十四章 GUI
1、 AWT框架基础
AWT 是Java 语言提供的用户界面设计工具,AWT 的基本思想是将一个窗口看做一系列嵌套的构件。最外层可以是窗口、菜单条、按钮或包容器等,而包容器又可以包含其他的构件或包容器。
一、 AWT包的结构
1) 组件(Component)
在AWT类层次结构的顶部是Component类,该类是一个封装了一个可视组件的所有属性的抽象类。在屏幕上显示的所有用于用户交互的用户界面元素都是ComPonent类的子类。
2) 容器(Container)
Container类是Component类的子类,附加了一些方法,允许别的Component对象嵌套在Container类的对象中,容器主要是负责布置它所包含的组件的位置。
3) 面板(panel)
Panel类是Container类的具体子类,它没有添加任何新方法,只是简单实现了Con
tainer类。
4) 窗口(window)
窗口类产生一个顶级窗口,顶级窗口不包含在任何别的对象中,它直接出现在桌面上。
5) 框架(Frame)
Frame类封装了窗口通常所需要的一切组件,它是window类的子类,并且拥有标题栏、菜单栏、边框以及可以调整大小的角。
6) 画布(Canvas)
Canvas类封装了一个你可以用来绘制的空白窗口。
二、 创建框架
用Frame创建窗口,可以是有标题也可以是无标题的。
注意:窗口的大小不能在创建窗口时指定,必须在窗口被创建后再设置窗口的大小。
1) 设置窗口大小
用setSize()设置窗口大小
2) 隐藏和显示窗口
当一个窗口创建后,这个窗口默认是不可见的,除非你用setVisible()方法。setVisible(boolean flag)如果参数为true,则是可见的,否则是隐藏。
3) 设置窗口标题
可以通过setTitle()方法来改变一个frame窗口的标题。
2、布局管理器的使用
布局:就是容器中组件的摆放方式,常用的布局管理器有:
1)FlowLayout(顺序)(默认):
将组件依次摆放,每个组件若不设置其大小都将被压缩到最小尺寸。
2)BorderLayout(边界布局):
将组件按north,south,west,east,center 五个位置来摆放。
3)CardLayout(卡片布局):
前后依次排列,每次只显示一个卡片。
4)GridLayout(网格布局):
将显示区域划分为若干行列,每个组件占一格。
3、事件处理基础
能产生事件的组件叫做事件源(如按钮),可给事件源注册一个事件监听器,当事件源发生事件时,事件监听器就代替事件源对发生的事件进行处理,这就是所谓的委托事件处理机制。
注意:事件监听器不一定是包容事件源的容器对象,只要一个对象实现了事件监听器接口就能成为事件监听器。这样处理可使程序中的事件处理代码与GUI 代码分离,有利于优化程序结构。在程序中编写“事件处理”程序段时,通常可以分为以下几个步骤:
(1)确定事件类型
(2)为部件增加一个该事件的监测器:通常名为XXXListener。这些接口包含在和 包中
(3)增加事件处理程序
总体来说,Java 事件处理有3 部分主要内容:
事件对象:表示事件的内容
事件源:哪个控件上发生了事件
Listener:事件发生了谁来处理
4、AWT的事件继承层次
要能够让图形界面接收用户的操作,就必须给各个组件加上事件处理机制。在事件处理的过程中,主要涉及三类对象:
Event-事件,用户对界面操作在java语言上的描述,以类的形式出现,例如键盘操作对应的事件类是KeyEvent。
Event Source-事件源,事件发生的场所,通常就是各个组件,例如按钮Button。
Event handler-事件处理者,接收事件对象并对其进行处理的对象。
由于同一个事件源上可能发生多种事件,因此java采取了授权处理机制(Delegation
Model),事件源可以把在其自身所有可能发生的事件分别授权给不同的事件处理者来处理。比如在Canvas对象上既可能发生鼠标事件,也可能发生键盘事件,该Canvas对象就可以授权给事件处理者一来处理鼠标事件,同时授权给事件处理者二来处理键盘事件。有时也将事件处理者称为监听器,主要原因也在于监听器时刻监听着事件源上所有发生的事件类型,一旦该事件类型与自己所负责处理的事件类型一致,就马上进行处理。授权模型把事件的处理委托给外部的处理实体进行处理,实现了将事件源和监听器分开的机制。事件处理者(监听器)通常是一个类,该类如果要能够处理某种类型的事件,就必须实现与该事件类型相对的接口。例如例5.9中类ButtonHandler之所以能够处理ActionEvent事件,原因在于它实现了与ActionEvent事件对应的接口ActionListener。每个事件类都有一个与之相对应的接口。
5、事件监听器接口
将事件源对象和事件处理器(事件监听器)分开。
使用授权处理模型进行事件处理的一般方法归纳如下:
1)对于某种类型的事件XXXEvent, 要想接收并处理这类事件,必须定义相应的事件监
听器类,该类需要实现与该事件相对应的接口XXXListener;
2)事件源实例化以后,必须进行授权,注册该类事件的监听器,使用 addXXXListener
(XXXListener ) 方法来注册监听器。
6、Adepter(适配器)类
Java语言为一些Listener接口提供了适配器(Adapter)类。可以通过继承事件所对应的Adapter类,重写需要方法,无关方法不用实现。事件适配器为我们提供了一种简单的实现监听器的手段, 可以缩短程序代码。但是,由于java的单一继承机制,当需要多种监听器或此类已有父类时,就无法采用事件适配器了
7、Swing概述
Swing 和AWT 的最大差别在于Swing 组件类不带本地代码,因此不受操作系统平台的限制,具有比AWT 组件更强的功能。
Swing 按钮类和标签类除了显示文本标题外还可以显示图像标题,可以为Swing 容器加上边框 Swing 组件能自动适应操作系统的外观,而AWT 组件总是保持相同外观Swing 组件不一定非得是矩形的,可以把按钮设计成圆形可以调用Swing 组件的方法心迹其外观和行为增加了一个丰富的高层构件集合,如表格(JTable)、树(JTree)。
一、特点:
类的属性被命名为xxx,则相应的的方法命名为:getXxx()、setXxx()、isXxx()
Swing 使用同AWT 相同的事件模型。处理Swing 中的事件时除了使用
包外,还要用到 包大多数情况下在老的AWT 组件前加一个“J”即为Swing 组件、
二、Swing 组件的分类
顶层容器:包括JFrame、JApplet、JDialog、Jwindow
普通容器:包括JPanel、JScrollPane、JtablePane
特殊容器:包括JLayeredPane、JRootPane、JtoolBar
基本控件:JButton、JCombox、JList、JMune、JTextFiled 等
不可编辑信息组件:如JLabel、JprogresserBar
可编辑信息组件:如JTextFiled、JTree、JFileChooer、JTable
第十五章 多线程编程(一)
1、 线程的基础概念和原理
线程也称为轻型进程(LWP),是比进程更小的运行单位,一个进程可以被划分成多个线程。当一个程序执行多线程时,可以运行两个或多个由同一个程序启动的任务。这样一个程序可以使得多个活动任务同时发生。
与进程不同的是,同类多线程共享一块内存空间和一组系统资源,所以系统创建多线程开销相对较小。
2、 线程的状态
线程有创建(New)、可运行(Runnable)、运行中(Running)、挂起(Not Runnable)、死亡(Dead)5 种状态。
一、可运行状态(Runnable)
Thread MyThread=new Thread()
();
这样该线程处于可运行(Runnable)状态,注意,这状态并不是运行中状态(Running),因为线程也许实际并未真正运行(因很多计算机是单CPU)。当一个线程正在运行时,它是可运行的,并也是当前正运行的线程。
二、不可运行状态(Not Runnable)
1)当下面四种情况发生时,线程就是进入不可运行状态:
(1)调用了sleep()方法
(2)调用了suspend()方法
(3)为等候一个条件变量,线程调用wait()方法
(4)输入输出流中发生线程阻塞
2)对于上面四种情况,都有特定的返回可运行状态的方法与之对应,对应方法如下:
(1)如果线程处于睡眠状态中,sleep()方法中的参数为休息时间,当时间过去后,线程即为可运行的。
(2)如果一线程被挂起,须由其他线程调用resume()方法来恢复该线程的执行。
(3)如果线程在等待条件变量,那么要停止等待的话,要该条件变量所在的对象调用
notify(),notifyAll()方法。
(4) 如果在I/O 流中发生线程阻塞,则特定的I/O 指令将结束这种不可运行状态。
三、死亡状态(Dead)
一般可通过两种方法实现:自然撤消或是被停止。
四、控制线程的状态
1)挂起一个线程:suspend( )方法
d():将t 暂停执行,必须由其他线程调用()恢复,不提倡使用该方法,因为容易造成死锁。
2)停止一个线程:stop( )方法
当线程完成运行并结束后,将不能再运行。另不可用()强行终止线程。注:这并没有消灭这个线程,只是停止线程的执行。但这个线程不能用()重新启动。不提倡采用这种方法,易造成线程的不一致。要通过设置flag 通知一个线程应该结束。
3)线程休眠:sleep(long )方法
()使一个线程暂停运行一段固定时间。
4)连接线程:join( )方法
()使当前的线程等待,直到t 结束为止,线程恢复到可运行状态。三种调用格式:
(1)join():如当前线程发出调用(),则当前线程将等待线程t 结束后再继续执行。
(2)join(long millis):如当前线程发出调用(long millis),则当前线程将等待线程t 结
束或最多等待mills 毫秒后再继续执行。
(3)join(long millis,int nanos):如当前线程发出调用(long millis,int
nanos),则当前线
程将等待线程t 结束或最多等待mills 毫秒+nanos 纳秒后再继续执行。
5)暂停(退让)线程:yield( )方法(只让给同优先级运行)
调用()方法可暂停当前运行线程,但处于可运行状态,让同优先级线程先运行。若没
有同等优先级的线程是可运行状态,yield 方法将什么也不做。
6)中断线程:interrupt( )方法
如果一个线程t 在调用sleep(),join(),wait()方法被阻塞时,则upt()方法将使t 的中断状态被清除,中断t 的阻塞状态,并且将接收到InterruptException
异常。
一个线程可以通过获取另一个线程的引用,调用该线程的interrupt()方法来中断另一个sleep或wait 线程的执行
7)了解线程的状态:isAlive( )方法
返回true 则线程处于Runnable 或Not Runnable 状态(即已启动但还没有运行结束),返回false 则说明线程处于New Thread 或Dead 状态
3、 创建线程
一、建立一个线程需要完成三件事:
1)建立一个虚拟的CPU
2)给出线程的执行代码
3)提供代码所操作的数据
二、两种方法可以创建线程:一种方法是通过继承线程类Thread 来创建线程类;另一种方法是建立一个实现Runnable 接口的类一创建线程 。
三、通过继承Thread 类创建线程
继承Thread 类这种方法中,需要覆盖run( )方法来提供线程的执行代码,定义Thread 类的成员变量来提供线程的数据。线程执行时,从它的run( )方法中开始执行,run()方法是线程执行的起点。
说明:
由继承Thread 创建的子类,必须覆盖run 方法,因为run 方法是abstact 抽象方法。
四、通过Runnable 接口创建线程
如果是Applet 类应不能再继承Thread 类(不能多继承),这时可以通过接口Runnable 直接创建线程对象。接口中只声明了一个未实现的run 方法。
线程体的构造方法:
public Thread([ThreadGroup group][,Runnable target][,String name])
其中group 指明该线程所属的线程组,target 是执行线程体的目标对象,它必须实现接口Runnable,name 则为线程名。这三个参数均可任意没有。
任何实现接口Runnable 的对象都可以作为一个线程的目标对象,类Thread 本身也实现了接口Runnable,因此我们可以通过两种方法实现线程体。
(1)定义一个线程类,它继承类Thread 并重写其中的方法run(),这时在初始化这个类的实例时,目标对象target 可为null
(2)提供一个实现接口Runnable 类作为线程的目标对象,在初始化一个Thread 类或者Thread 子类的对象时,把目标对象传递给这个线程实例,由该目标对象提供线程体run()。这时实现接口Runnable 的类仍然要以继承其他父类。
第十六章 多线程(二)
1、 线程的优先级
Java 为使有些线程可以提前得到服务,可给线程设置优先级。在单个CPU 上运行多线程时采用了线程队列技术,Java 虚拟机支持固定优先级队列,一个线程的执行顺序取决于其对其他Runnable 线程的优先级。优先级分1~10 同,默认级别是5 级。
2、 线程的同步
虽然多线程能给我们带来好处,但是也有不少问题需要解决。例如,对于像磁盘驱动器这样独占性系统资源,由于线程可以执行进程的任何代码段,且线程的运行是由系统调度自动完成的,具有一定的不确定性,因此就有可能出现两个线程同时对磁盘驱动器进行操作,从而出现操作错误;同步多线程(SMT)是一种在一个CPU 的时钟周期内能够执行来自多个线程的指令的硬件多线程技术。本质上,同步多线程是一种将线程级并行处理(多CPU)转化为指令级并行处理(同一CPU)的方法。 同步多线程是单个物理处理器从多个硬件线程上下文同时分派指令的能力。同步多线程用于在商用环境中及为周期/指令(CPI)计数较高的工作负载创造性能优势。
处理器采用超标量结构,最适于以并行方式读取及运行指令。同步多线程使您可在同一处理器上同时调度两个应用程序,从而利用处理器的超标量结构性质。
使隶属于同一进程的各线程协调一致地工作称为线程的同步。MFC提供了多种同步对象,下面我们只介绍最常用的四种:
临界区(CCriticalSection)
事件(CEvent)
互斥量(CMutex)
信号量(CSemaphore)
第十七章 网络编程
1、 java网络基础
一、 socket套接字
应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了称为套接字(Socket)的接口。
区分不同应用程序进程间的网络通信和连接,主要有3个参数:通信的目的IP地址、使用的传输层协议(TCP或UDP)和使用的端口号。通过将这3个参数结合起来,与一个Socket绑定,应用层就可以和传输层通过套接字接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。
二、 InetAddress类
InetAddress类在网络API套接字编程中扮演了一个重要角色。参数传递给流套接字类和自寻址套接字类构造器或非构造器方法。InetAddress描述了32位或64位IP地址,要完成这个功能,InetAddress类主要依靠两个支持类Inet4Address和Inet6Address,这三个类是继承关系,InetAddrress是父类,Inet4Address和Inet6Address是子类。
1)getLocalHost() 方法
用 getLocalHost() 方法创建的InetAddress的对象,此时getHostName返回的是本机名。
2)getHostAddress()方法
定义:public String getHostAddress()
该方法用来得到主机的IP地址,这个IP地址可以是IPv4也可以是IPv6的
三、 Socket类
网络应用分为客户端和服务端两部分,而Socket类是负责处理客户端通信的Java类。通过这个类可以连接到指定IP或域名的服务器上,并且可以和服务器互相发送和接受数据。在本文及后面的数篇文章中将详细讨论Socket类的使用,内容包括Socket类基础、各式各样的连接方式、get和set方法、连接过程中的超时以及关闭网络连接等。
四、 ServerSocket类
与Socket类相对应,ServerSocket类用于表示通信双方中的服务器端。该类可以监听客户端发送的连接请求并进行处理。ServerSocket类的构造方法主要有如下几种。
ServerSocket ():无参构造方法。
ServerSocket (int port):创建ServerSocket对象,并监听指定的端口号port。
ServerSocket (int port, int backlog):使用指定的backlog创建ServerSocket对象,同时绑定到指定的本地端口号port。
ServerSocket(int port, int backlog, InetAddress bindAddr):使用指定的端口号port创建ServerSocket对象,同时监听backlog并绑定本地IP地址bindAddr。
创建了ServerSocket类的对象以后,服务器可以对指定的端口进行监听。通过调用ServerSocket类的相关方法可以接收客户端的请求从而与之通信。
2、 实现通讯程序
原理是在服务器端建立ServerSocket端口并监听,接收到客户端的连接请求时建立Socket,得到Socket的输入输出流。在客户端新建Socket并获得输入输出流。服务器和客户端的输入输出流建立后使用writeLine()和println()方法彼此发送和接收数据。为提高代码效率,建立两个类clientAgent和serverAgent。
3、 建立URL
一、 URL的定义:
Uniform Resource Locator的缩写。一个使用文本指代WWW网站上任意数据的标准。一个URL通常是这样的"protocol://host/localinfo",protocol指明传输对象的时候使用的协议(比如HTTP或FTP),host指明在Internet上找到一台主机的名字,localinfo是一个传递给远程主机上协议处理器的字符串(常常是一个文件名)。
二、URL类
URL类的构造方法主要有如下几种
URL(String spec):使用指定的字符串构建。
URL(String protocol, String host, int port, String file):使用指定的协议、
主机名、端口号、文件名创建。
URL(String protocol, String host, String file):使用指定的协议、主机名、文件名构建。
URL(URL context, String spec):使用基地址和相对URL创建。
版权声明:本文标题:JAVA初级知识点大总结 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/p/1709758929a545437.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论