一》java介绍
java编程的区域规则:
1.由一个个类构成(类相当于c语言中的结构体)
2.类里面只有属性和方法两块区域。其里面不可能存在语句区域。
3.方法里面才是语句区域和局部变量区域。异常操作都是操作代码语句,
所以必然只能在方法里。(比如main方法和其他方法)
1.java的特点
简单易学
- 相当于是c语言的变种,所以大部分语法规则还是与c相近
- 摈弃了c语言较难的一部分,如指针和内存管理
- 提供了丰富的类库
- java是完全面向对象的语言,而c++是面向对象和面向过程的中间体,c是纯面向过程
安全性高
- 如语法严格性,如int i=1.11;这样是不允许的,因为可能会造成数据丢失。
- 如摈弃了c语言中较危险的指针和内存管理问题。这样就不会直接对硬件操作,也就不会有问题了
- 内存管理,java会自动清除堆中内存,而c语言需手动free()。
跨平台使用
- 用户实现用代码控制电脑之间的逻辑关系
- 跨平台到底什么意思 跨平台指的是源程序编译后的文件可以在不同电脑的不同操作系统下使用,而不同的操作系统会有只能识别特定文件,不能识别其他文件。c语言跨平台能力弱,而java可以跨遍不同平台
- java的跨平台原理
java源程序通过编译后得到了字节码程序,然后利用不同的操作系统下的特定的虚拟机(这个虚拟机是适合这个所在的操作系统的),将字节码转换成该操作系统下能够识别的机器语言。
2.C和java的对比
理解c语言代码操作过程
c语言经过编译之后形成可执行文件.exe,这个执行文件是操作系统可以“看懂的”然后经过操作系统将其转化为指令,然后给cpu解读,然后再把执行结果返回给操作系统,然后在执行软件方面操作。 所以不同的操作系统可能对文件处理方式不一样
C语言和java语言的操作运行区别
java虚拟机解释
不同的电脑下载的java虚拟机肯定是不同的,设计他的人肯定知道不同的java虚拟机为不同的操作系统和硬件所量身定做的。但不同的java虚拟机可以编译通用的编程语言,这就是设计java虚拟机的灵魂所在。导致了java可跨平台
3.其他的一些解释
为什么不给c语言也加一层虚拟机呢
1.速度问题。加了一层虚拟机从代码编译后到操作硬件底层的速度会变慢,也就是得到结果
会变慢
2.设计问题。我们设计c语言就是让它能够快速操作硬件且易编写而设计的。而java就是让其
具备跨平台功能,方便移植
粗略解释为什么大部分软件现在都用java写了
1.java跨平台,可移植性强,这就导致了软件可以在不同的操作系统下运行,然后给cpu计算,
得出操作和结果
2.java面向对象,c语言面向过程,C语言逻辑性强,写软件没有java容易
二》面向过程和面向对象理解和区别
面向过程
优点:
1、分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现。
2、以算法为核心,
3、自顶向下设计,要求一开始必须对问题有很深的了解
4、将大问题转化为若干小问题来求解
5、表现形式:用函数来作为划分程序的基本单位
6、直接面向问题
缺点:
数据和操作分离开,对数据与操作的修改变得很困难;数据的安全性得不到
保证,程序架构的依赖关系不合理。
面向过程
其设计思想是,一个问题有哪几部分问题或事物组成,然后有类来模拟这些事物,把这些事物所有可能的操作全部包含在这个类中。这是一种自底向上的设计思想
1.类和对象和过程比较
2.c语言中结构体和类区别
3.使用类和使用结构体区别
- 局部变量和成员变量(属性)的区别
三》标识符和数据类型
1.标识符
以字母,下划线(_),美元符($)
开头的一个字符序列,
后面可以跟字母,下划线,美元符,数字
2.数据类型
数值型
- 常量
#整型常量
#浮点常量
#字符常量
Java中字符和字符串都用Unicode编码表示
区别点:在于其char占2个字节,但英文字还是低8位有效,中文字才16位有效
#布尔类型
用boolean表示,不能写成bool;布尔型数据只有两个值true
和false
,且他们不对应于任何整数值。参与逻辑表达式的计算结果。
引用型
类,接口,数组
所对应的输出控制符其他的一些区别
输出数据格式
与c语言不同的是
%d(int, long int, short, byte)
%f(float,double)
%c(char)
数据类型的转换
1.容量大的到容量小的,必须使用强制类型转换。要不然报错
2.容量小的到容量大的,会自动转化
占的字节个数
运算符
加法
位运算符(需要用到补码知识)
四》类和对象的理解
1.类
解释:
把一类事物静态属性和动态可以执行的操作组合在一起所得的这个概念就是类,类是抽象的,用来模拟一类事物,是一个概念,一旦定义了,类的概念就永远存在
使用说明
-
里面的内容
* 组成 1.属性(静态属性)+方法(构造方法和方法)(动态操作) * 说明 1.只能定义属性(可同步初始化),但无法再进行赋值等其他操作 (想想结构体不也不行么) 2.可以在方法内部进行对同类属性操作 (想想函数当然可以)
- 与c语言相比较
1.可以将类类似于c语言中的结构体,所不同的是 类包含了这个事物的静态属性和动态操作(方法),而c语言结构体是只包含了一个事物的静态属性,而动态操作是通过外部函数来实现
所以类只是模拟,定义了类,物理上没有为其分配内存(这与c语言是一样的),只有定义了其对象时,这时里面的东西就是确实存在了,在堆中分配了内存
类里其实就是属性+方法(\函数),而c语言把属性(结构体)和函数分隔开了,这也就是面向对象,面向过程的一种体现
主类的解释:
-
含义:主类的标志是包含main的类,其整个代码都是从这个类中的main进,main出,
-
注意:
1.当主类没有定义成公共的时候,其类名可以与文件名不一致\ 2.当主类定义成公共的时候,其类名必须与文件名一致\ main的格式固定 public static void main(String[] args)
其他类的解释:
- 含义:描述一个事物的静态属性和动态可以执行的操作组合在一起所得到的
- 与主类的关系:是并列的关系
- 一个类中包含若干属性和若干方法和若干重载构造函数
2.对象
解释:
对象是类的一个个体,具体的实实在在存在的事物,当定义了对象时,物理上会在堆内为其所指的类分配内存(其内存大小是其类中的属性和方法所占的空间大小之和),也会在栈内为对象分配内存(其内存大小是固定值,一般
4字节)
这其实会发现和c语言指针为结构体分配空间时非常相似了
格式:
-
格式 类名 +变量名=new + 类名(形参...)(也就是构造方法);
-
调用类中的属性和方法 1.变量名.属性/方法(前提是无private)
2.类名.属性/方法(前提是该属性和方法均要为static和无private)
注意事项:
1.一个项目中只能有一个公共的类,且其类名必须与文件名一致,
也称这个类叫主类
2.特殊的,还有个超类问题
-
注意:
1.类名前面不能加任何访问控制符 2.格式固定class +名 3.
-
当定义对象时,若类中无进行初始化,则各个成员都是已被自动初始化0了
但有一点区别就是属性变量和局部变量的区别
属性变量在类中,方法之外定义,当未初始化时, 而定义类对象时,里面的值被赋予默认值 局部变量在方法中被定义,再使用的时候必须进行初始化。
与c语言的一些类比:
* 格式类比
A aa=new A();//在堆内为A分配内存
struct A * aa= (struct A *)malloc(sizeof(struct A))//也是在堆内分配内存
你会发现struct A * 缩成了A,替换了指针的概念,所以java虽说无指针,但
是逻辑思想还是没有改变
* 调用类比
java: aa.属性;
c语言:aa->属性或*aa.属性
***总结而言:java在语法上与c语言相似很大,
而解决问题的思维逻辑两者是从不同的角度出发的,这样对不同的问题就有各自的优势
程序代码中的内存管理
heap 堆
stack 栈
静态变量和字符串常量 一块区域,时间周期长
例如字符串常量
String A="aaa";
String B="aaa";则A和B是同一个事物
访问控制符
以下均是在同一个项目中的
- 如何理解同包同类
- 如何理解同包不同类:
1.同一包中同一java文件中的多个不同类
2.同一包中不同java文件中的不同类 - 如何理解不同包不同类;
- 不同包不同类继承,private表示在父类中用private定义的属性或方法无法被继承到子类去,自然无法被访问。
- 不同包继承 不要写默认
- 不同包的
下面表明,
1.public就是一个访问控制符
2.不存在什么主类,在一个工程中,所有类的地位是并列的
3.main表明了一开始运行的时候是从main进入,从main出,而在main中可以调用其他类,main之所以用static 表明只能存在一块区域,是所属类的。
函数重载、
构造函数
-
格式注意 1.“函数名”与类名需一致
2.无返回值
注意:1.构造函数里可以是任何符合语法规则的内容和非私有的外部属性和方法 2.当构造一个其类的对象的时候,会自动运行构造函数里的内容\ 3.一个类中一定有构造函数(方法),当你不写的时候是默认public A() 所以这就是当是默认时为什么有定义对象是 A aa=new A();
函数重载
封装
this关键字
1.为什么有this的存在
由于一个对象只含有属性的空间,n个对象共用一个方法的拷贝
如当存在两个A类对象时,如A aa,A bb;
aa.f(12);
bb.f(11);
由于是两个不同内存的对象使用同一方法的模板,java语言中是如何区分的,
计算结果和操作时是如何对内存检索操作的
其void f(int i, * this指针)
{
this.i=i;//this表示的是aa所指向的地址,
//this.i就是某个对象中的属性变量,而i是局部变量
}
this就是当前的对象,可以通过其来调用当前对象中的成员。
1.this调用成员变量和方法时,是充当了指针概念,this.属性名或方法名
2.this调用该类的其他构造方法时,直接用this(实参....);
static啊含义
static 只用于修饰方法和属性。
敲代码部分
1.访问控制符使用,类和对象
继承:
1.介绍:
由来:
当多个类存在共有的属性或方法时,我们可以定义一个父类,将这些共有的属性和方法写在一起,然后定义类来继承他,这些类也就叫做子类。代码的利用率大大提高了,这也就是继承的由来。
优点:
代码得到极大重用
形成一种类的层次体系结构
为多态创造了条件
基本格式:
class 父类名{} class 子类名 extends 父类名{}
注意:
性质:
单根性:即一个子类只能有一个父类
传递性:B继承A,C继承B,则C也继承了A里的内容
注意:
1.子类只继承了父类的非private的属性和方法。
2.子类可以继承非private的static修饰的方法和属性,但无法重写其static方法
3.子类无法继承父类的构造方法,只能用super进行调用,然后继承其里面的调用的结果
2.super关键字
关键字的作用:
1.访问父类非私有属性和非私有方法。
格式:super.属性或方法();可在方法和构造方法中写;
意义:调用属性也是将其结果继承到子类里来
2.访问父类的构造方法:
格式:super(实参.....);对应着父类中的构造方法来,只能写在构造方法里
意义:调用父类对应的构造方法,虽不能继承其构造方法,但是用super语
句可以继承其构造方法里的执行结果。
注意:
1.super关键字只能出现在子类当中,但每个用户定义的类必然有父类,只是毋庸置疑的。
2.super若是调用父类的构造方法,则必须放在子类构造方法中,且必须是第一
条语句,也就表明了只能有一个super调用构造语句
3.使用this来调用本类其他构造方法是不可以与super调用父类构造方法一起
的。由于都要求写在第一行
4.若子类构造方法没有写super关键字,
则系统默认在其构造方法第一条为super();无参调用父类构造方法
5.父类若无写构造方法,其实系统也是默认写了构造方法
public 父类名(){};
super与this的比较
子类调用父类的构造方法的解释:
3.子类对象实例化过程
即:先调用后实例化,后调用先实例化。
解释:
由于子类继承了父类的东西。子类的实例化必然牵涉到继承的父类的东西的实例
化,但如果父类没有先实例化被创造,则子类不可能完整被实例化创造。
所以继承体系中,一定是由顶向下实例化的。
而调用则是自下向上的。
- 注意:
- 关系
包含关系,范围关系,使用关系
4.方法重写
为什么需要方法重写
由于子类继承的父类的方法可能不满足于子类的实际需要,而是新增了功能和特性操作
。则我们可以进行方法改写,使满足子类特定的需要。
注意:
特点:
1.方法名称必须和父类相同
2.参数类型,个数,顺序相同
3.子类重写父类的方法,返回值类型必须与父类相同或是其子类
4.子类重写父类的方法,访问权限不许大于等于父类的访问权限
注意:
1.重写的方法必须是非private类型的
2.无法重写static类型的方法,static方法归类所有
3.子类不能重写父类的构造方法
- 如何使用或获取其他类中的私有属性和方法 1.调用其他类中共有的方法,这个公有的方法包含对私有属性的操作
抽象类
1.abstract关键字
abstract关键字可以修饰类和方法,分别定为抽象类和抽象方法
2.抽象方法和抽象类的具体说明
抽象类:
格式 abstract class A
含义:抽象的事物,无法定义对象,只能定义其引用
更多的是进行标志意义
注意:
1.包含抽象方法的类必须声明为抽象类
2.抽象类中可以有抽象方法和具体方法
3.##具体类继承该抽象类时必须把其里面抽象方法全部实现了##
4.当然抽象类也是可以继承抽象类的
5.当具体类继承抽象类时,必须对抽象方法必须要##全部进行重写##,需要符合重写的规范
而抽象类继承抽象类则不用
抽象方法:
格式:修饰符abstract+返回值类型+函数名();
含义:起一个标志该函数的作用,无函数体
注意:
1.实际中,需要在具体类中用*方法重写*将其表达的功能给实现了
3.解释抽象类在java中的作用
利用抽象类的作用主要是定义抽象的事物,比如猫科动物,猫科动物有许多许多分支,但其中都有共同的特性和行为。当我们需要把这个猫科类系全部模拟出来,形成树状。最顶端或者上层的可定义为抽象类,抽象类的内容可以是抽象的方法把这些猫科动物所共有的特性抽象描述出来。而细分到具体的动物时(树状下层),则就是可以定义具体的类,里面的内容可以是将抽象类中的抽象方法具体根据该类的性质来具体实现或者该类的其他的特性方法。
所以定义抽象类是为了将其下共有的特性用抽象方法给描述出来,到具体实现时是到具体类中的具体方法中实现。
4.抽象类中的多态
抽象类不可以定义对象,但我们可以定义引用,则我们就可以利用这一点来进行多态
final关键字
final关键字可用于修饰类,类中属性,类中方法
1.修饰类
当修饰类时表示这个类无法被继承
2.修饰属性
1.修饰引用类型变量
表示一定要先初始化实例对象,然后其指向的空间无法再改变。但是其里面
的成员变量是可以改变的。
2.修饰普通成员变量
表示:一定要初始化,且其值不能被修改
**但其本质:还是值未被改变
普通成员变量初始化
1.定义变量同时初始化
2.在该类·构造方法·中进行赋值初始化
3.修饰方法
当修饰类中普通的方法时则表示这个方法无法再进行改写
接口 interface
1.接口介绍
定义:
是抽象方法和常量值的集合,只能包含抽象方法和常量值,而定义时的数据类型修饰符都是固定的。也是一种特殊的抽象类
接口使用格式
(public) interface 接口名 (extends 1,2,3...的接口名)
使用时的几个注意
说明
1.类与抽象类的关系一样
2.class A extends B implements C(,D,E...)
3.意义大致和抽象类一致,但接口由于可以多继承,这导致功能上可能有所不同
4.接口不能有构造方法
5.注意多态的运用注意
6.具体类必须实现所有接口的抽象方法,实现部分时必须定义抽象类
7.接口中定义的属性无法再被更改,因为final
2.接口作用
3.抽象类与接口的区别
1.抽象类里面可以有具体的方法,但接口里只能是抽象方法
2.抽象类的属性和方法的数据类型访问修饰符无具体要求,
而接口中数据类型访问修饰符只能是固定的
3.接口可以被多实现和继承,而抽象类只能被单一继承
类和抽象类和接口对比:
1.格式不同,
类和抽象类都是class,接口是interface
抽象类还要用abstruct进行修饰
2.是否能实例化
1.类可以实例化,而抽象类和接口均只能定义引用(便于多态使用),无法实例化
2.所以类可以有构造方法,而接口没有构造方法。
虽说抽象类不能被实例化,但是他可以有构造函数。
这是因为当抽象类作为父类时,抽象类中可能又含有具体方法和具体成员
属性,根据实例化过程我们知道,##父类需要实例化来建构子类对象##
3.内容规定不同
类可以包含任意属性和方法,且修饰符都是不确定
抽象类也是包含任意属性和方法,且修饰符不确定,
但有抽象方法的类一定要定义为抽象类
接口是抽象方法和常量属性的集合,
且修饰符固定: public abstract,public static final
4.final的修饰
类可以使用final,其不一定要被继承才有用
抽象类和接口不能使用final,因为抽象类和接口一定要被实现里面的东西才有用
5.多继承多实现
抽象类和类均只能单继承
接口可以被多继承
多态
1.什么是多态
一个父类的引用类型既可以指向父类对象,又可以指向子类对象。可根据当时所指向的对象不同,而进行不同对象的操作。这就是多态
2.注意事项:
1.父类A,子类B,定义A aa,B bb。可以aa=bb;不可以bb=aa;
2.父类引用所指向的子类,可以被强制转化然后赋给另一个。而引用所指的父类是无法被强制转化。
含义:
- 利用多态不能访问子类中所特有的成员(方法,属性),适用于继承和实现接口中 类,抽象类,接口
- 那么如何利用多态来进行调用子类中特有的方法呢? 强制转换,这个到事件处理的时候会详细讲到
包
- 同包中的不同java文件中的类访问
- 不同包中的java文件夹下的不同类访问
- 不同路径的不同包中的类访问
lang包解释
protected 的用法
内部类可以使用,同java文件下也可以使用修饰类,但不同的java文件下不能使用
jar包
命令行 jar cvf T.jar *
异常
1.java中的异常是什么
异常就像生活中的不确定事件,这个事件有时可能发生,可能不发生
。由于一些现实问题,比如除数不能为0,用户通过键盘输入数据与所获取的数据类型不一致这一类不确定事件导致程序运行异常。而引入异常处理就是为了解决这一问题。程序员可以通过思考某个语句事先可能发生的异常事件,通过异常处理结构
进行捕获,然后处理该事件。
-
异常和错误的区别
错误 error:一般指系统语法上的错误,一般编译时就会报错。 程序员无法对正在运行的程序进行处理修改正确。 运行终止 异常 exception:编译时是正常的,但一运行就会异常,报错。 程序员可以进行异常的捕获,然后对其异常进行相应的处理 异常处理可以使其运行不终止
2.异常的代码规范
1.异常所需用到的关键字
try,catch,finally,throw,throws
2.try-catch-finally结构(异常处理结构)
如图结构所示
说明:
1.try里的代码块中可以是任意代码块,但当try中某个语句其所调用的操作发生异常,
则其语句下面的代码段无论如何都将不会在被执行
2.try要么不异常,要么只能对一个异常进行处理
3.catch的多重。要求捕获异常类型顺序是子类在前,父类在后。
且多重catch只会执行一个
4.try-catch-finally执行原理;
出现异常时,首先是与第一个catch中的异常类型进行匹配
* 匹配成功,那么则执行其里面语句,其他catch作废,结束catch后,
然后执行finally,然后再执行该结构下面的语句
* 匹配不成功,则往下再去寻找匹配,如果找不到,
则就执行finally,然后再执行该结构下面的语句
5.finally可有可无,finally无论是否捕获到异常都会执行。
6.只存在三种结构:
1.try-catch
2.try-finally
3.try-catch-finally
- finally关键字
3.throw和throws关键字
-
throw关键字
throw用于抛出异常(可以是系统异常,自定义异常) 格式:throw new 异常名(参数),可理解为抛出了个异常对象空间 抛出后,有两种方式来处理: 1.就在该语句下来进行捕获处理 2.用throws(throw代码必须是方法中的内容),将代码抛给上一级 上一级又将会有相同的两种方法来处理 注意: 如果异常被throws层层抛出,始终未找到捕获进行处理,则需要最终一定将会在main中 再次被抛出,抛出给虚拟机,虚拟机则会输出错误信息,然后终止程序运行
-
throws 其方法下的语句产生异常时,把与其相兼容的异常类型信息给抛出去,抛到其调用的语句处,再次寻找处理的结构(try-catch-finally)或者再次找到throws(再次给抛出去)。
说明: 结构:方法后缀 throws+异常类型(异常类型,..,,,,用逗号隔开) 注意: 如果异常被throws层层抛出,始终未找到捕获进行处理,则需要最终一定将会在main中 再次被抛出,抛出给虚拟机,虚拟机则会输出错误信息,然后终止程序运行
此图说明了,我们抛出时异常类型必须是相兼容的,相匹配的,否则无法被
抛出
或者无法被捕获。
3.异常的运行过程
即为捕获异常处理结构和throws-throw的结合进行。
- 当问题语句发生异常,若既有立刻try捕获异常处理和throws抛出两种方式,则先是执行try处理语句,若其不匹配异常类型,再将其进行抛出,否则不会被抛出。
- 哪里有问题,哪里直接进行处理
- 哪里有问题,将问题抛出,给上级处理(可以层层抛出)
4.异常的分类
Throwable分为Error和Exception
Exception又分为`可处理可不处理异常`和`必须处理异常`
可处理可不处理异常:编译时不会出错,运行时如果执行了
可能异常的语句才会报错,将异常对象抛出
不执行则不会报错(一种潜在异常)
必须处理异常:存在即报错,编译时就会出错,
会将异常对象抛出,所以必须得进行*异常捕获处理*
常见的可处理可不处理异常(RuntimeException):
1.ArithmeticException
2.NullPointerException
3.NumberFormatExcetpion
4.ClassCastException
5.ArrayIndexOutException
6.IllegalArgumentException
必须处理异常(ChackedException):
1.ClassNotFoundException
2.NoSuchMetodException
3.IOException
5.异常的几个常用语句;
1.e.printStackTrace(打印)
2.System.err.println("");
3.e.getMessage返回值为错误信息的字符串
6.自定义异常
- 用于异常的继承,来实现先检测哪个异常先
- 自定以异常和系统异常的区别
- 为什么需要自定义异常
7.异常的提示
1.当程序遭到异常突然终止(未做处理,层层抛给虚拟机终止)
会打印出堆栈信息
2.当程序遭到异常,但做了try-catch处理则不会显示错误信息,
程序会运行下去 ,不过可以利用e.printStackTrace() 堆栈信息
- 打印的堆栈信息
8.C语言与java对异常的处理
C语言和java中的异常都是指编译可以进行,但运行时会出错(语义上出错)。
c语言对于异常处理是直接忽略,直接那条语句作废,然后继续执行下面的语句
而java比较严谨,异常也会报错,当无进行异常处理时会直接终止程序。所以java给了异常这个处理结构
9.使用系统给的类的时候
经常由于严谨性,系统给的类,程序员编写好的是否会抛出异常是根据需要来的,所以在使用系统类时注意其可能抛出的异常问题,其我们利用类调用其中的方法
10.异常的作用
#敲代码
数组
object中的toString和equles方法
object说明
1.所有的类都继承了object类且每个java文件中都是自动导入了java.lang包(java.lang包中存在object类)
object中的toString方法
重写toString方法
-
原始object中代码
public String toString(){ return getclass().getname()+"@"+Integer.tohexString(hashCode()); } 即返回值为包名+类名+@+16进制的哈希码值
-
常在其继承的子类描述自身性质时需要改写以便更好描述笨类所代表的含义 如:
public String toString(){ return "姓名:"+name+"\t年龄:"+age+"\t身份证号码:"+identify; }
toString方法的调用
-
1.当用于输出时,不用于赋值,则直接写对象名视为默认调用,对象名会自动调用,P; == P.toString(); 如:System.out.println(p);
-
对象名+toString()即可;
object中的equals方法
object类中的equals
为什么需要重写equals方法
根据实际需求,当想比较相同类
中相同属性
的值比较时,则需要重新根据需要写
- 敲代码
- 理解 public boolean equals(object obj) 这里object是包含多态的知识
常用类、
string类
- 理解 "y".equals("y");
- String中的equals
- String引用类型问题:存储值相同;
数组
介绍:
数组是一个容器,其里面存储的数据既可以是基本数据类型,又可以是引用数据类型
数组的使用
一维数组的定义
未赋初始值时:
int [] a=new int[长度];//java写法
int a[]=new int[长度];//c语言写法
未赋初始值时,由于分配数组是堆内存,则初始值为0或null
赋初始值时:
int []a=new int[]{1,2,3,4};
int []a={1,2,3,4};
之后赋初值或改变值:
则是直接与c相同 a[0]=10;
数组的常用操作
-
遍历:
使用for循环: int[] a={1,2,34,5}; 1.普通for循环 for(int i=0;i<a.length;i++) { System.out.print("\t"+a[i]); } 2.加强for循环 for(int i: a){//意思为按顺序从a中取出数来赋给i,直至该数组的长度 System.out.print("\t"+i);
二维数组的定义
未赋初始值时:
*声明:int[] a[];
int a[][];
int[][] a;
*开辟空间:
无int[][] a=new int[][];
int[][] a=new int[7][];//只确定了可以存储一维的数目(行),也只开辟了行数内
存,其里面为null,存储地址
int[][] a=new int[7][8];//确定了行,列,行分配的空间存储地址,而列分配的空间
存储什么和其类型有关
赋初始值时:
int[][] a=new int[][]{{1,2,3},{1,2,3,4},{1,2}};
int[][] a={{1,2,3},{1,2,3,4},{1,2}};
之后赋值:
*对于只开辟行来说(int[][] a=new int[7][];)
能a[0]=new int[]{1,2,3,4};//右边是一维的数组开辟
不能a[0]={1,2,3,4};
或者int[] b={1,2,3,4};
**a[0]=b;//a[索引]就是用于存放地址的**
注意要首先为列开辟空间,才能进行赋值和利用索引修改值
*对于开辟了行列( int[][] b=new int[7][8];)
由于已经为列开辟了空间,
则无法使用b[0]=new int[]{1,2,34};
1. 但是知道b[索引]是用于存放地址的,则我们可以进行赋值,进行改变指针指向
如:int[] a=new int[]{1,2,3,4};
b[0]=a;这样是可以的
2. 利用索引b[n][m]一个一个赋值
注意:
二维数组:
a[n] 存储地址,存储一维地址
a[n][m] 一维数组存储数据
三维:
a[n] 存储地址,存储一维地址
a[n][m]一维数组存储地址,再存储一维地址
a[][][]存储数据;
其他维数均可这样推导
三维:a[3][4][2]
引用类型数组和基本类型数组
1.引用类型数组,例如类
A[] a=new A[10]//表示定义了10个引用,在栈中,所以并未开辟内存。
开辟内存的错误方法:
加强for循环:
for(A i:a){//这个表明将a的值依次顺序给i,而开始a并未开辟空间,所以为null
i=new A(....);//则这个只是给了个寂寞。
}
正确做法:
普通for循环
for(int i=0;i<10;i++){
a[i]=new A(....);
}
2.字符串引用类型特例:
3.基本数据类型
依次赋值的操作最好也是用普通for循环;
String和StringBuffer
-
String
-
注意: 1.String str=new String(abvc)与String str="abvc";
String str1=new String(abc); String str2=new String(abc); str1和str2所指向的内存不是同一块区域,这是在堆区;
str1.equals(str2)==ture;成立,这是因为String类中改写了equals方法;
String str1="abc"; String str2="abc"; 而这str1和str2所指向的区域均是字符串的同一块区域,这是在字符串区:
str1.equals(str2)==ture;成立
-
StringBuffer
线程
1.线程的介绍
-
程序,进程,线程
程序是指可由计算机看的懂的一系列顺序的指令集合, 计算机按照其指令来进行对相关对象的功能实现和操作 进程是指启动运行的程序,系统会为其分配一定内存空间 进程由三部分组成,数据,代码,cpu 线程是进程的组成部分,一个进程可有n个线程, 线程占这个进程的共享内存和资源, **cpu在一个时间片只能中执行一个线程** cpu在一个时间片中调度一个线程,这个线程可来自不同的进程中的不同线程。
-
单道
-
多道
2.实现线程的方法
第一种继承Thread类
1.class A extends Thread{
public void run(){
}
}
注意:
1.必须重写Thread中的run方法,
且其访问修饰符和返回值和形参均固定public void 无
** 且其无法抛出异常,由于父类不会抛出异常,所以不能抛出异常
第二种实现Runnable接口
1.class A implements Runnable{
pulbic void run(){
}
}
A a=new A();
Thread t=new Thread(a);
t.start();
由于A中无start方法,所以只能用Thread类来搞出start方法,
而重写run方法在A类中
注意事项和上述一样
-
如何理解:
A aa=new A(); Thread t=new Thread(aa); t.start(); 理解就是Thread t=new Thread(aa);这条语句中的构造方法可能实现了aa对象继承t 然后aa类中又存在对Thread类中的run方法进行重写, 然后我们调用Thread对象的start,其实是调用aa对象中的 run方法
执行线程中的内存解释;
两者区别
1.经常用第二种方法来实现多线程。因为涉及同步原因,实际问题。抢占统一资源,则可以用第二种方法,创造多个Thread引用指向同一资源。
注意事项
1.注意重写方法的访问修饰符的规则。
3.开启线程
满足条件:
1.实现线程方法时已经重写了run方法
2.调用t.start();才是开启线程
** 注意:t.run()不是开启线程,和单纯调用函数一样 **
4.线程Thread类的常用构造方法
1.new Thread();
2.new Thread(Runnable taget);
3.new Thread(String "线程名字");
4.new Thread(Runnable taget,String "线程名字");
5.线程的生命周期
就绪状态:start();,yield();
运行状态:
阻塞状态:join();,sleep();wait();
死亡状态:1.线程执行完毕2.stop()停止3.获取到未捕获的异常(此时整个进程都会终止)
6.线程的常用方法
来自Thread类)
1》static
1.Thread currentThread()
2.sleep(long millis);//休眠
3.yield();//让一次出资源
2》final
1.String getName();
2.int getPriority();
3.setPriority();
4.stop();//停止线程
5.boolean isAlive();
6.join();//强制执行完成线程
来自Object类
均是final
1.wait();//使该线程一直处于等待状态
2.wait(long timeout);//使线程处于等待状态,等待的时间
3.notify();//唤醒任意处于等待状态的线程
4.notifyAll();//唤醒所有等待的线程
**等待的线程,只有被其他线程唤醒才可以被cpu调度了**
使用这些方法的注意:
1.来自不同类的方法的区别:
来自object类的线程方法,只能在同步代码段或是同步方法中使用
来自Thread类的线程方法,可以在任何方法任何地点使用
object类的线程方法,释放对象锁:这使得可以让出同一资源
Thread类的sleep不会释放对象锁。
2.几个方法的规则:
sleep()是必须处理异常,所以必须捕获,
**一般来说只能用捕获,而不能抛出,这是因为重写run方法,无法抛出异常**
7.线程的同步和死锁
8.线程之间的通讯
- 线程
-
创建线程的第一种形式
-
创建线程的第二种形式
-
第一种方式和第二种方式的区别
-
Thread中常用的方法
9.thread的操作
线程优先级
设置线程名字和获取线程名字
方法一:(利用Thread类中方法)
1.对象名.setName();
2.Thread.currentThread.getName();/aa.getName();
//thread.currentThread的意思是获取当前线程的引用
方法二:(利用构造函数)
new Thread("线程名字");
new Thread(引用,“线程名字”);
- 线程让步
- 线程串行
-
线程挂起和恢复
-
终止一个线程
10.同步问题(买票程序)
synchronized关键字
-
格式:synchronized(对象名)
-
注意
1.synchronized()修饰代码块(一般用在run方法中)和方法。 ·修饰方法·时一般是修饰其他方法, 而run方法不用,用run方法调用其他被synchronized修饰的方法 1.synchronized里面的程序段执行完,才会释放出对象,取消霸占 2.当执行synchronized里面的代码时,也会存在线程转移, 只是其他线程无法在霸占synchronized的对象名(当没被释放时), 则就无法执行其里面代码段
问题:
3.定时器和我们线程的区别 4.多个线程对同一资源进行操作时才会出现同步互斥
gui
流
- 流大纲
一、流定义
流就是带有按钮的管道,按钮就是不同的对于管道的操作方法,管道就是连接程序和设备之间的传输数据的媒介
二、流类介绍
一.流分类
-
广分: 节点流(原始流)和处理流(包裹流)
-
细分: 抽象流;inputStream,outputSteam,Reader,Writer
原始流:FileReader/Writer,FileinputStream/outputStream
包裹流:缓冲流,数据流,object流,print流,转换流- 原始流就是单根管道,而包裹流是基于原始流之上再加一层管道。
- 包裹流就是在原始流的基础上新增一些功能使得传输效率更高,方式更多。
其中我们使用得一般都是继承这四大基本抽象类 inputStream,outputSteam,Reader,Writer
三、各个流(具体类)的详细介绍
一、原始流传输数据 file+四大基本抽象流
-
1.file的解释
* file是指传输任何格式的文件,而+四大基本抽象流。 表示不同的传输方向,和传输数据的单位。 * file是节点流(原始流)
-
2.常用基本方法。
inputStream
outputStream
read字符流
write字符流
-
3.注意:
注意: 1.在使用流的时候,都要进行异常处理。基本上抛异常即可。 2.注意各个方法的使用。功能,形参,返回值 3.对比方法的使用,记忆更深。 4.输出流一般都要加上刷新缓冲的语句 fw.flush(); 5.打开多少个流,记得使用完关闭,减少资源占用。close(); 6.**字符流一般用于文本文件的传输,字节流可以传输任意格式的文件,更强大。**
-
4.缓冲区
缓冲区的好处,加快写入硬盘的速度,保护硬盘。一次性写入 流的缓冲区刷新,new FileinputStream.flush(); 所以只适用于输出流。
-
5.用字节流和字符流的区别。 1.每次传输的数据单位不同 这导致了如果将文本进行传输用字节流显示到程序运行的结果时,由于输出控制符·转换问题,导致中文会乱码(一个字节用两个字节来输出,会有问题),存在编码和解码问题。
而用字节流将文本进行传输到文本文本文件时,那与字符流进行传输时无差别的。
这是因为不存在输出控制符了,存储显示本来就是数据,和传输的数据单位无关系。
二.缓冲流
-
1.基本介绍
* 缓冲流是包裹流 * 缓冲流的四种构造方法和四个类的写法熟悉,别搞错了。、 * 优点:
-
2.中转枢纽作用
*[]buf/ch作为程序中的中转枢纽,连接传输中的输入和输出。 过程: *当输入管道连接两个设备时(程序<-文件), 输出管道连接两个设备时(程序->文件), 此时[]buf/ch起的就是中转作用,将输入的数据接收再输出出去。 缓冲流时:先是数据通过缓冲输入管道进入缓冲区, 然后再到[]buf/ch中,然后[]buf/ch中的数据先是发送到发送缓冲区 ,然后再通过缓冲输入管道\*一并\*发送给连接的设备
-
3.注意:
注意: 1.一般来说文本与音频相比较,文本所占字节少,音频则比较大, 所以文本可用数组媒介或者单字节,而音频一般用单字节缓冲流传输 2.数组的中转枢纽作用。 字节流(字节)传输用 byte数组, 字符流(字符)传输用char数组 但如果字符流传输用的是readLine方法则中转枢纽用String 3.缓冲字符流时: 1.bw.read()读到文件末尾返回-1; 2.br.readLine()读到文件末尾返回null; 注意两者的差别 4.缓冲流特有的br.readLine() 但注意读到不同的地方其返回值不同, 比如读到每一行末尾时,其返回为空字符串“”。暂停该行读取,开始下一行读取 而读到文件末尾时,其返回为null。暂停文件读取,不再读取数据。 注意区分和理解
-
4.数组作为中转枢纽传输文本格式文件是的讨论:
大小有所不同,这是因为定义了3000字节数组,然而有效部分是1665左右,所以写入时,是写入整个数组还是写入数组有效部分,这会影响文件的大小。文件内容几乎不会变化。
三.数据流
-
1.介绍
* 数据流是包裹流 * 以一种特殊方式,直接从底层字节流进行按照需求对传输的数据类型进行 转换成其他基本类型数据输出和输入
- 2.用数据流进行网络传输的实例运用:
解决从long型转换成byte型进行传输,然后再将byte型传输数据转换成long型;
就是传输时的数据类型为byte,而两头的数据类型可以是任意的;
四、转换流
-
介绍: 为了将一些不同继承类别的类进行转换其他的类可以进行使用了
-
编程例子:
-
注意:
* 本例中的键盘输入,终止读取时readLine()返回值与 文本文件终止读取时返回值的不同。
五、print流
- 1.介绍 print流既可以是包裹流,又可以是原始流
- PrintStream流
- PrintWriter流
- 用例:
-
注意:
print流的写法是 PrintStream pr=new PrintStream(OutputStream os);继承OutputStream流 PrintWriter pw=new PrintWriter(Writer w);继承Writer流 既可以包裹流,也可以原始流 按照上面所说的,所以可以将通道中基本类型数据 转换成字符串形式写入到所连接的设备中
-
print流和System.out.print()的区别点
1.System.out.print()就是用print流来进行实现的, 只不过是System.out.print()被定向用于输出到显示器上面了。 2.print是流,可以连接不同的设备, 然后将要传输的数据转换成字符串类型写入连接的设备。 3.System.in/out/err都是与print流有关,重定向的时候就知道了
六、标准输入输出的重定向
- 注意使用 System.setOut/Err/In(PrintStream ps);来进行重定向
- 整个流程过程和原理清除明白
七、对象序列化(object流/接口)
三、其他要注意的东西:
文件的后缀名和文件分类无关。
文件没有后缀名,并不会改变文件里面的内容,还可以正常打开运行。
后缀名的作用:
1.方便用户清楚文件的类型,自己所形成的分类
2.作为文件的标记,操作系统会根据其后缀名,使用特定软件打开,并且为默认。
没有后缀名时,操作系统无法识别,则我们可以手动指定特定软件打开。
所以后缀名只是个标记,并不能实质上分类。
理解编码,解码。更好理解字符流和字节流区别
* 编码:用预先规定的方法将文字、数字或其它对象编成数码,
或将信息、数据转换成规定的电脉冲信号,
编码是信息从一种形式或格式转换为另一种形式的过程
* 解码:编码的逆过程。
* 为什么会出现编码解码问题:解决字符和数字之间转换问题,
使得我们认知的字符可以转换成特定数字被计算机看懂,并用数字传输。
* 为什么会出现乱码:实质原因是编码和解码不统一。
就好比:从网上下载的源代码,中文会乱码,
这是由于在编写时编码标准和打开查看时用的解码标准不一样导致的。
所以只需要更改一下查看时解码标准就可以了。
* 程序是用计算机语言编写的,自然也会涉及字符,自然也就存在编码解码问题:
就好比:一个文件为什么必须用特定软件打开。若用txt文本打开qq会怎么样?
* 所以我们的字符流必然存在编码解码问题,而字节流不会存在。
搞清楚流的基本框架和关系
文本文件传输:
1.字节流传输:数组,用byte[]接收
单个字节,用int接收
2.字符流传输:数组,用char[]接收
单个字符,用int接收
缓冲字符流的一行读取,用String接收
音频类文件传输:
1.字节流传输:单个字节
2.缓冲字节流传输:单个字节
缓冲流处理问题:
1.加快传输音频类文件的速度,保护硬盘
2.文本文件一行读取问题
3.连接键盘设备,用一行读取问题
数据流处理问题:
就是处理流的数据,读取发送与传输时不同数据类型转换
转换流问题:
print流问题:
就是处理流的数据,读取发送与传输时的数据类型String转换
容器
一、容器大纲
二、为什么需要容器
*容器比数组更强大,我们可以存储不同类型的数据,
但以相同的方式存储起来,即全部转化为对象存储起来。
*利用L.add()实现添加//该语句实现任何类型的数据全部转化为对象进行存储至容器中
三、容器的分类
set,List,Map
四、Colection和list和Set和map接口中定义的方法说明
Colection接口中方法,作为老大
List接口中方法,继承Colection接口
其具体实现的类有:LinkList和ArrayList
- 方法
- 两者的区别点:
Set接口中方法,继承Colection接口
其具体实现的类有:HashSet,TreeSet,LinkSet
Map接口方法,自己单独老大
五、List接口
toString()问题
Collections类的介绍:
Collections类中的倒叙,排序方法
注意:
我们使用Collections操作容器实现功能时:
1.Collections(List L)操作参数一定要搞明白;
2.Collections操作的容器,容器里面的对象必须是·同类的对象·才可以,
且实现了Comparable接口的CompareTo()方法,定比较标准。
二分查找:一定是要先有顺序才能查找。
查找的比较是比较对象中的全部内容。
Comparable接口问题
-
使用Collections比较两个类对象的时候,需要制定比较标准,否则无法比较,无法排序。所以出现了Comparable接口问题;
比较的类肯定是相同的类,不能把学生和车比较吧 Collections.sort(L),肯定是里面自动调用了L中的compareTo()方法 compare接口实现两个同类型的类进行比较标准。
六、set接口
介绍:
1.set接口是无序的和无重复的
2.set接口实现的具体类有HashSet,TreeSet,LinkedHashSet
3.set由于是无序的,所以没有Collections类的操作和get,set等方法操作
set几乎和Collection接口的方法一致。
HashSet
-
介绍:
优点:添加速度快查询速度快删除速度快 缺点:无序
-
无序原理: 以哈希表为内核的存储方式实现无序。当添加元素至HashSet容器时,调用其类中所给的HashCode方法,不同的类不同内容返回的值不同原理,然后在内存一一映射,即达到了无序。
-
不重复原理: 利用了哈希表和equals方法重写的比较原理。相同类对象不同内存同一内容返回哈希码值相同
-
*总结来说(理清整个添加到容器过程)
*当调用语句new HashSet().add(A(..)); *首先会自动调用A中的hashcode方法,返回一个属于A对象特定的“哈希码” *然后根据哈希码,在容器(内存)中找到指定的区域(哈希码值与位置一一映射) 然后这个位置放的是另一块内存中所定义链表的首地址。 *然后由于链表中存放了其他对象,然后要将A对象放进去,而且要实现不重复原则。 (相同类对象不同内存同一内容返回哈希码值相同) 则我们需要进行比较这个位置的链表是否存在同类相同内容的对象 所以如果要比较对象的内容的话,则我们需要重写该类中的equals方法。 *然后会进行调用该类中的equals方法,进行比对。若有相同,则不能放进去,反之。
什么类需要重写,什么类不用重写
以哈希表为内核的存储方式的容器需要重写
如:HashMap,HashSet需要重写
TreeSet,List不用重写
一般系统自定义的类都重写了HashCode()方法。sum公司已经设计好的了
如Intget,String......
用户自定义的类,且需要存放在以哈希表为内核的存储方式的容器中需要进行重写
如何重写HashCode方法和equals方法:
-
利用sum公司已经设计好的类里面写好的HashCode方法进行重写我们自定义类中的HashCode()方法
int i; String name; public int HashCode(){ return new String(this.i+this.name).HashCode(); }
-
equals方法重写 和之前重写一样;
public boolean equals(object ob){ 该类类名 st=(该类类名) ob;//进行强制性转化 return st.i==this.i&&st.name==this.name; }
注意:
1.容器是如何进行存储类的?会分类吗?
以哈希表为内核的存储方式,在链表中进行存储对象。不会分类,无序。
2.一个地址代表一个链表,链表上存储的是同一类的对象吗
链表存储的不一定是同一类型的对象
3.哈希码的产生相同和不同的是以什么条件?
哈希码产生根据不同内容而产生不同。
4.清楚s.add(new A())的实现存储过程
上面已经写清楚了
System.out.println(s);就实现了遍历?
5.什么容器需要重写equals和hashcode方法:
以hash表为内核的存储方式的容器需要重写:hashSet,hashMap,hashTable
6.哈希方法如何重写,equal如何重写
List接口中的方法
注意:
* 添加到容器里的对象,对象的toString()方法一定要进行重写
问题敲代码
- System.out.println(L);//L为List型,表示其里面按照数组顺序,执行类.toString()方法(数据->字符串转变,这也就是流的问题了)。
- 抽象类,接口都可以创造引用。但无法给实例化对象。
所以具体的类我们需要改写,否则出问题。
7.泛型:
网络编程
网络基础知识:
什么叫做网络程序:
就是一个设备运行程序之后,可以通过网络这一媒介
将数据
发送给另一台设备或接收另一台设备发送的数据。
预备知识:
- IP地址:
总的来说就是一个IP地址代表一台电脑,这个IP地址作为网络传输数据的起始地或者目的地。具备全球唯一性。局域网和互联网之间有差别。这里面IP地址很复杂,涉及什么字码掩码等东西,之后具体了解。
-
端口号: 当一台设备从所连接网卡中接收到数据时,电脑此时运行了多个程序,那么这个数据最终去向哪个程序,肯定是必须确定的,否则不同数据到达不同程序,涉及编码解码问题就会出错且运行也会有问题。
所以设计了端口号,来使得特定的数据到达特定的程序
-
通讯协议: 简单来说就是指如何去发送数据,通过什么形式发送而制定的标准和规范。 存在加密,解密过程。但里面原理什么很复杂,之后再去了解。
利用上面三个准备的在网络上传输数据的流程。
UDP编程(以传输Long型数据为例)
UDP就像码头发送货物一样(或者发短信)\
A程序建立一个码头,再建立一个带有数据,和目的地标识(快递包裹(程序中是IP地址和端口号))的集装箱
有了目的地直接发送即可。
B程序建立一个码头,再建立一个集装箱装特定的数据(就是目的地),
当数据运送过来时,装箱即可
所以其整个过程并没有连接关系,只是目的地明确,直接发送即可。所以不免会遭到货物丢失情况。所以风险比TCP高
* 客户端编程过程:
1.定义一个发送码头
2,将发送的数据进行转化成集装箱能装的类型(byte[]型)
3.定义集装箱(数据,IP地址,端口号);
4.利用码头发送集装箱;
5.关闭码头
* 服务端编程的过程:
1.定义一个接收码头(定义端口号)
2.定义byte数组,用于存放接收过来的数据便于显示在程序上
3.定义集装箱(定义的byte数组)
4.等待接收请求(当客户端发送完毕时)(是个阻塞语句)//此语句完毕后,集装箱已接受到数据
5.再将集装箱类型的byte数据转化为原始要发送的数据,然后再显示在频幕上
6.关闭码头
* 数据类型的演变过程
`long型`
通过数据流操作转化成byte[]数组(程序->数组)
`byte数据`
然后将byte数组放入集装箱中
发送
接收
接收时再用一个byte数组来从集装箱中取出来。
`byte数据`
通过数据流操作转化成Long型(程序<-数组)
`Long型`
- 获取IP地址:
TCP编程
TCP就像打电话一样(A程序发送请求),必须有人接(B程序响应),才能互相说话(传输数据)
过程就是请求,响应,传输数据。
请求,响应建立连接管道,数据在其上面传输。
发送端和接收端进行连接,传输数据可靠,不易丢失。
编程过程:
所谓连接成功是指这两个网络程序建立了一个通信管道,双方都可以通过这个管道写数据和读数据,并且一方写入的数据实际就是另一方要读取的数据,一方要读取的数据实际就是另一放要写入的数据, 即这个管道实际是双向的,任何一方都可以通过getInputStream() 和 getOutputStream()获取输入流和输出流两个流,并且一方的输入流实际就是另一方的输出流,这是同一个流,一方的输出流实际就是另一方的输入流,这也是同一个流 即一个通信管道两个流,双方各自都可以得到两个流,这两个流分别是输入流和输出流\
并且UDP其实也是可以双向进行传输数据的,只是传输方式不一样。
UDP和TCP两种方式编程的差异
TCP两端刚开始有明显的主次(就和打电话一样,打电话的人是请求,接电话的人是接收)。只要两者互通了。那么就没有主次关系了。谁先接收信息都可以的。
UDP两端是等同的。发消息随时发,发多少条都没关系。不需要任何回复都可以。但也是存在缺点:就是由于可能会出现无法按时准确对指定传输的数据进行操作和回复的现象。所以UDP一般用于聊天。
服务器和客户端的区别点:
1.服务器一般用于存储数据和对数据进行操作,结果是产生数据结构。
和对客服端发来的请求进行传送客户端想要的显示数据。一般TCP编程。
2.客户端一般用于显示方面内容的操作,进行和客户交互。对于客户的需求进行发送请求到服务器端,
得到显示数据即可。所以不能直接操作相关的数据。
所以服务器端一般不会关闭,可能关闭数据就丢失了。
但如果及时存储到硬件设备中,下次重启在读取。那么再关掉服务器后,数据也可以得到保存
InetAddress类
InetAddress并无构造方法; 获取IP地址办法:
1.InetAddress ia=new InetAddress.getByName("主机名称");//获得Inet对象。
2.ia.getHostName();//返回主机名称
3.ia.getHostAddress()//返回主机IP地址。
new InetSocketAddress(intAdr,port);//这个是定义发送包裹的时候写的