## JAVA基础
第一章: 相关了解
背景:Sun Oracle Eclipse
版本:5.0(现在大部分人学的是5.0语法) 7.0 8.0(用8.0作项目开发) 11.0
特点:半编译半解释 ,通过JAVA虚拟机实现跨平台
命令:javac 文件 .java (编译) , java 类名 (运行)
- 我们编写的代码文件(.Java)要经过编译器编译成字节码文件(.class)再经过jvm解释成特定平台的机器语言文件(二进制文件)
配置:java安装路径下的bin目录位置配置到环境变量的path中
JDK和JRE的区别和联系?
- jdk是Java开发工具包,不仅提供程序运行所需的jre,还提供了编译、运行等功能,比如:javac、Java、javaw在程序员的电脑里当然要安装jdk
- jre是Java运行环境,用户的电脑上可以装jre
有全局变量 (保证变量不乱,即使重名) 就近原则:嵌套块中如果有同名的变量,谁近用谁 变量种类:变量不被赋值不允许使用,类里的变量除外
- 局部变量:函数内声明,生命的周期就是函数的调用
- 成员变量:(又叫属性)在类中声明,生命周期属于某一个对象,每一个对象有自己的一套成员变量
- 类变量:(又叫静态变量)在类中声明,但是有static修饰,生命周期属于所有类和对象,所有对象和类共享一个变量。
基本数据类型 | 字节 | 取值范围 |
---|---|---|
byte | 1 | -128~127 |
short | 2 | -215 ~215-1 |
int | 4 | -231~231-1 |
long | 8 | -263~263-1 |
float | 4 | -2128~2128-1 |
double | 8 | -21024~21024-1 |
boolean | 1 | 0 or 1 |
char | 2 | -128~127 |
含义:1111111111(二进制)=1024(十进制)=1Bytes(字节)=8bit(比特)
一个英文字母或者一个阿拉伯数字就是一个字符,占用一个字节
一个汉字就是两个字符,占用两个字节
byte b=128; 输出b的结果为-128?????????????????
java中默认给的是int类型,现在需要转成byte类型
intl类型128二进制:00000000 00000000 00000000 | 100000000 由于byte是一个字节,所以前面三排0要舍弃,10000000为-128
证明如下:
byte:-128=-127-1 二进制中的负数用补码表示
+127 原码 01111111 +1 00000001
反码 10000000 11111110
-127 补码 10000001 11111111
(-127)+(-1)等于10000001+11111111=10000000 即-128
引用数据类型:
- 数组
- 类
- 接口
数据类型转换:
基本数据类型转换: 不是同一个类型不允许运算
显示:1 小转大随便 2 大转小容易出问题,看数据是否超出小类型的取值范围,如果超出则溢出
隐示:大小规则 byte > int > long >float > double
short
引用类型转换:向上转型:????
向下转型:????(数据类型转换的首要前提是两者之间有继承关系)
运算符: - 算术运算符:+ - * / ++ – %
- 连接运算符:+
- 比较运算符:> ==(永远比较值本身) < !=
- 逻辑运算符:&& || !
短位:&&左边是false,则右边不计算
||左边是true,则右边不计算 - 位运算符:& | ^ >> << >>> ~
- 赋值运算符:= += -= /= *=
- 三目运算符:? :
位运算符^、&和|的区别? - ^(异或):二进制数值在同一位上不相同,则结果中该位为0
- &(与):二进制数值在同一位上都为1,则结果中该位为1
- |(或):二进制数值在同一位上只要有一个1,则结果中该位为1
++i和i++的区别:
++i先自增,再运算;i++是先运算,再自增
int a=4;
int b=0;
b=a++ + ++a;//b=4+6=10(前面的a是先把值交出去运算,当遇到++a时,他的自增还是要运算的)
流程控制语句
switch是否支持byte,是否支持long,是否支持String?
1. jdk1.5版本之前:支持byte,short,int,char
2. jkd1.5版本之后:支持枚举
3. jdk1.7版本之后:支持String
4. 到目前为止,还不支持long。原因:switch底层使用int类型判断的,即使是枚举、String也是转换为int型后判断的。由于long类型的表示范围大于int型,因此不支持long
第六章:面向对象
面向过程:
面向对象:oop
面向对象语言:c++,java,javascript,python基于对象的语言es6面向对象
思想:人类认识世界,理解世界的本源思想
利用面向对象思想解决现实问题:
- 解决问题需要哪些个体?
- 体升华成概念
- 概念通过语法生成类文件
- 计算机通过类文件生成对象
- 程序员通过运行和操作对象模拟现实问题
语法:
类:人类设计对象的模板
class{
属性:描述是啥?
变量
行为:描述要干啥?
方法
[嵌套类]:由什么组成?
}
对象:计算机要模拟的实际参与业务的个体(信息和功能的载体)
类与对象的关系: 对象是类的代表,对象可以调用类中定义的所有属性和方法; 类是对象的模板
构造器:可以在类中定义一段代码,通过new来创建对象;如果类中没有构造器,则系统默认会送一个无参构造器,如果有则系统不送;无参构造器由名字和类名一致,没有返回值类型
构造器有叫构造函数或构造方法,但构造器绝对不是函数和方法
构造器本身能被new创建对象,我们为什么还要写呢?
方便快捷完成初始化对象
this:当前对象,解决了当前类属性名和局部变量名相同的冲突问题
构造器怎么创建对象的?
new默认自动创建对象,并把对象的地址引用临时交给了this,最后交给了栈里的引用
构造器中如果使用了this()和super()必须放在第一行
匿名对象:只有new和构造器,没有引用的对象,依然可以调用类中定义的所有属性和方法
优点:性能强 缺点:不能重复使用,不能记录数据
消息:对象之间相互调用或者操作传递的信息(传参)
第七章:面向对象的高级特性
封装:
访问权限:类,方法,变量
public:共有(所有都可以用)
protect:保护的(同一包里可以使用,子类以自己的身份也可以使用)
default/friendly:默认的(同一包里可以使用)
private:只有本类可以使用,子类也不可以
how:利用访问权限控制符和流程控制语句(对所有属性私有,同时提供getter和setter方法)
使用时应注意:封装后的属性只是创建对象之后不能修改属性,而不是不可以创建对象。通过getter方法可以获得属性,通过setter可以修改属性。所谓的封装就是在getter和setter方法里添加条件限制,使一部分人不可访问和修改属性
what:对自己开放,对外界封闭
why:解决了全局变量问题(所有人都可以使用和修改同一个变量)
继承:
子类是父类的一种
why:便于重复使用已有代码,便于修改和维护(在实际开发中,直接在原来的代码上修改,可能会影响原来代码的功能,重写一套的话,代码的复用性和维护性又很低)
how:extends otherclass
what:使用extends的类叫子类/派生类;被extends的类叫父类/超类 /基类
Java基础中一个类只能有一个父类,一个类可是多个类的父类
没有extends的类的默认父类是object
子类可以使用父类中定义的多有方法和属性(private修饰的除外),子类允许有自己的方法和属性且和父类无关
super:当前对象的父类对象
子类对对象诞生的前提是诞生父类的对象,子类构造器默认调用父类构造器
子类对象诞生的过程:(Java虚拟机加载过程)
1.先加载父类
①先加载父类的静态属性
②再加载父类的静态块
③最后加载父类的静态方法
2.然后加载子类
①先加载子类的静态属性
②再加载子类的静态块
③最后加载子类的静态方法
*******以上只在第一个加载中执行一次
3. ①父类的普通属性,父类的普通快,父类的普通方法,父类的构造器
②子类的普通属性,子类的普通快,子类的普通方法,子类的构造器
*******第三步每创建一次对象就执行一次
(静态属性>静态块>静态方法)>(普通属性>普通快>普通方法)
多继承:
内部类+接口
内部类(嵌套类):
用处:
- 访问外部类所有资源
- 对外界不可见
- 解决多继承冲突(当类,接口,(抽象)父类三个不同组合,发生方法名冲突的时候,此时必须用内部类来解决——我的收藏里详解)
四种内部类:
- 成员内部类:不允许有静态属性;Outer.Inner oi=new Outer().Inner();
- 静态内部类:静态内部类只能访问静态的外部资源;Outer.Inner oi = new Outer.Inner();
- 局部内部累:为方法准备,只能在方法内使用,可以访问方法的局部变量
- 匿名内部类:用于接口和抽象类的实例化,匿名内部类必须实现所有抽象方法
各种类的权限修饰符?
-
外部类:public、default。(由于包与包直接没有继承,所以用protected修饰类是没有意义的)
-
抽象类:public、protected。
-
接口:public。
-
内部类:语法上都可以用(个人觉得内部类就是用private和static private保证私有化,static保证使用方便,用public就违背了内部类的原则)
接口:解决多继承问题,类可以实现多个接口,接口可以继承接口,接口不是类
接口中的属性:public static final 修饰
接口中的方法:public abstract(1.8之前)
default(1.8之后)
为了方便对比我把抽象类知识也记在这儿:
抽象类:可以有抽象方法,也可以没有抽象方法;抽象类中可以有构造器,但是不允许直接用构造器实例化对象
抽象方法:必须去掉方法后面的代码块,一个类只要有抽象方法则必为抽象类
接口和抽象类的区别? -
接口是被类实现;抽象类是被类继承(接口可以多继承,而抽象类只能单继承)
-
接口中的方法只能为抽象方法;抽象类中既可以有抽象方法,也可以没有抽象方法
-
接口中的变量是公共静态的常量(public static final 修饰);抽象类中的变量是普通变量
-
接口是设计的结果,抽象类是重构的结构
普通类和抽象类的区别?
- 抽象类不能被实例化(尽管他有构造器)
- 抽象类的抽象方法不能是静态的,只需声明,无需实现(静态方法可以被直接调用,而抽象方法没有方法体,所有声明为静态的没有意义)
- 抽象类的子类必须实现父类的所有抽象方法,否则子类也必须是抽象类
多态:
前提条件:
1有继承关系
2有方法的重写
3父类引用指向子类对象
重写:返回值类型一样,函数名一样,形参一样,子类的访问权限控制符必须高于或等于父类
好处:尽可能通过父类统一接口保证程序稳定,通过子类重写的方法保持系统更新或修改
引用数据类型转换:不是所有数据类型都能转(必须有继承关系)
隐示:父类引用指向子类对象,肯定不报错;向上转型
显示:子类引用指向父类对象,有极大可能报错(成功的前提是父类对象本身就是子类对象);向下转型
父类引用指向子类对象:父类引用调用方法时,如果子类重写了就坚决使用子类的方法,如果子类没有重写就使用父类的方法(方法中的属性无论是否有继承或者多态干扰,属性的前面有个this.——永远优先使用方法所在类的属性)
instanceof:判断左边的引用或者对象是否属于右边的类型或者子类类型
用于向下转型避免出现异常
异常:
throwable:问题
- error:错误(暂时不管)
- exception:异常
exception:
- runtimeexception:运行时异常,有算术,指针,数组下表越界等异常。不建议用异常处理机制(水平不够)
- otherexception:检查性异常,有IoException等异常等。必须用异常处理机制
处理异常的几种方法:
- try/catch:try捕获异常,catch 处理异常。catch可以有多个,要求子类异常在上,父类异常在下(try与catch是绑定的)
- throws:抛出异常方案,在方法体外使用
- throw:主动抛出希望处理的异常,方法体内使用(自己创造出来的异常,即当初开发Java的程序员没有想到的)
error和exception的区别?
1. error一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢出等。(仅靠程序无法恢复和预防)
2. exception表示程序可以处理的异常,可以捕获且可能恢复。
throw和throws的区别?
throw:
- throws方法体外使用,throw方法体内使用
- throws是声明这个方法可能会抛出这个类型的异常,调用者必须做出处理(捕获或者继续抛出),否则编译不能通过;throw是具体向外抛出异常的动作,所以它抛出的是一个具体异常的实例
- throws可以单独使用,但throw不能。throw要么和try-catch-finally配套使用,要么和throws配套使用;throws可以单独使用,然后再由处理异常的方法捕获
throws:
- 方法的定义上使用throws表示这个方法可能抛出某种异常
- 需要有方法的调用者进行异常处理
final,finally,finalize的区别?
1.final:final是修饰符
- final修饰的类不能被继承
- final修饰的方法不能被重写
- final修饰的变量不能被不能被二次赋值
2.finally:finally是在异常处理时提供finally块执行任何清除操作。不管有没有抛出或者捕获异常,都必须执行。所以在代码逻辑中有需要无论发生什么都必须执行的代码,可以放到finally块中 。
3.finalize:是方法名,finalize()方法是在垃圾回收器将对象从内存中清除出去之前,做必要的清理工作。这个方法是垃圾回收器确定对象没有被引用时,对此对象调用的。
集合
collection和collections的区别?
- java.util.Collection是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法
- java.util.Collections是一个包装类,它包含了各种有关对集合对象操作的静态多态方法,此类不能被实例化,就像一个工具类。
list、set、和map的区别?
- list中元素有放入顺序,元素可重复
- set中元素无放入顺序,元素不可重复(元素虽然无放入顺序,但元素在set中的位置是由该元素的hashcode值决定的,其位置其实是固定的)
- map元素按键值对存储,无放入顺序,key不可重复,value可以重复
arraylist和vector的区别?
- ArrayList的默认大小是10,每次增长原来的一半;vector默认大小也是10,但每次增长原来的一倍
- ArrayList线程不安全;vector线程安全,支持线程同步
- ArrayList的性能比vector好
ArrayList和linkedlist的区别?
- ArrayList是数组实现的;linkedlist是链表实现的
- ArrayList查询数据块(利用index直接返回元素),修改数据慢(插入和删除元素位置之后的元素的位置都需要移动);linkedlist查询数据慢(需要在双向链表中找到index后,才能返回元素),修改数据快(不需要改变数组大小,和元素位置)
hashmap和hashtable的区别?
- hashtable的默认大小是11,增长方式为old2+1;hashmap的默认大小是16,增长方式为old2
- hashtable线程安全,支持线程同步;hashmap线程不安全,性能强一点
- hashtable的包含方法是contains;hashmap把contains改成了containskey和containsvalue
- hashtable不支持null值;hashmap中key可以有一个null,value可以有多个null
如何决定使用treemap还是hashmap?
- treemap会对键进行排序,如果想要按自然或者自定义顺序存入和遍历,treemap会是更好的选择
- hashmap可以根据键取值,访问速度快,在map中插入、删除和定位元素,haspmap是最好的选择
什么是迭代器?
迭代器,提供一种访问一个集合对象各个元素的途径,同时又不暴露该对象的内部细节。hasnext()方法判断集合对象是否还有下一个元素,next()得到每一个元素
Iterator和Listiterator的区别?
- iterator是通用的,listiterator只能list使用
- iterator和listiterator都有hasnext()和next()实现顺序向后遍历。但listiterator有hasprevious()和previous()可以实现逆向遍历
- iterator和listiterator都可以删除数据,但listiterator可以实现对象的添加和修改,add()和set()可以分别实现,而iterator仅可以遍历
- listiterator可以定位当前索引位置,nextindex()和previousindex()可以实现,但iterator不可以
iterator怎么使用?特点?
用法:
- hasnext()方法判断集合对象是否存在下一个元素
- next()方法取出每一个元素
- remove()方法删除元素
特点:
- iterator对集合元素进行遍历时,不允许线程对集合元素进行修改,否则会抛出异常
- iterator必须依附某个collection对象而存在,iterator本身不具有转载数据对象的功能
如何实现数组和List之间转换?
- 数组转List:
```java
第一种:Arrays.asList(arrays) 这种方法生成的List不能add()和remove(),且长度固定和数组相同
第二种:Collection.addAll(list,arrays)//list是自己提前创建好的集合 List<String> list = new ArrayList<>();
- List转数组
List.toArray(new String[list.size()]);//String 是原集合中元素类型,list.size()是原集合长度
文件与流
网络传输
TCP和UDP区别?
- TCP是面向连接,可靠的传输协议;UDP不是面向连接,不可靠的传输协议
- TCP发送速度比UDP慢
- TCP能保证数据有效和有序传输,而UDP保证不了(发动数据数据包完成以后,对方收到数据底层会回复,这样TCP就能重传和错误脚校验)
多线程
进程和线程的区别?
- 进程是操作系统级别的实现多任务的手段;线程是程序内部实现多任务的手段(线程是进程的执行单元)
- 进程之间数据不可以共享;线程部分数据可以共享