# JAVA
标签(空格分隔): 后台
---
JAVA:面向对象编程
对象的生命周期:从new开始到垃圾回收之间
##1.对象的三个特征:
封装:封装的就是对象的特征和行为,封装完就是类
继承:就是一个类继承于另一个类,不断向上继承,子类可使用父类的一部分东西
多态:多种状态
###(1).封装
定义:利用抽象数据类型对数据信息以及对数据的操作进行打包,将其变成一个不可分割的实体。
1>将对象的状态(属性)和行为(行为)看成一个整体,将内容封装到类内
2>信息隐藏
关键字:private
封装将类的数据隐藏起来,控制用户对类的修改和访问数据的程度
**作用:**
1.隐藏数据信息,避免恶意修改带来的安全问题
2.封装之后可以供多处调用,减少程序的耦合度
3.类内部的结构可以自由更改而不会影响其他代码
4.能够对成员属性进行精准的控制
###(2).继承
定义:从多种实现类中抽象出一个基类,使其具备多种实现类的共同特性。
关键字:extend。
**作用**
1.实现代码复用,避免代码冗余
2.代码结构层次清晰
3.为了实现多态
Java在继承上默认类继承于object类,继承具有传递性,单继承。
子类用重写重新定义父类的方法或者自己定义自己的方法。
实例化对象时,子类默认调用父类无参构造方法,在调用子类构造方法。当父类不存在无参构造时出错。
构造方法的调用必须放在第一行,只能调用一个构造方法。
###(3).多态
面向对象的程序设计语言最核心的特征。
定义:一个对象有着多重特征,可以在特定的情况下,表现不同的状态,从而对应着不同的属性和方法。
**作用**
1.消除类型之间的耦合关系 。
2.可替换性(substitutability)。多态对已存在代码具有可替换性。
3.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。
4.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。
6.可扩充性(extensibility)。多态对代码具有可扩充性。
实现多态的前提和要求:
1>必须有继承关系。
2>重写。
3>向上造型。
##2.关键字
####1.super
代表调用的当前对象的父类对象,super会延继承方向寻找调用的方法一直到object。
####2.this
代表当前对象,调用此类的对象。
####3.static
static 可以修饰属性(成员变量,字段),方法
static 修饰的内容属于类的内容,不属于对象
static 修饰的内容为唯一的一份,对象之间共享该数据
static 修饰的内容随着类的加载而加载
类成员(static 修饰的内容)
可以修饰变量及方法 所有对象共享
使用static修饰的代码块为静态代码块
static初始化 在一个程序之中只加载一次
####4.final
不能修饰代码块
修饰成员变量,初始化后不能再赋值
修饰方法,方法不能被重写
修饰类,类不能被继承
####5.Synchronized
java 中的同步锁
使用同步块可以减少同步范围,提高并发效率,但是要保证,多个线程看到的同步监视对象是相同的!或者没有同步现象。
synchronized还可以实现互斥锁。当synchronized将不同的代码加锁,只要锁的对象相同,那么这些不同的代码就具有互斥性
synchronized修饰的方法及代码只允许一个线程调用
注:代码块:
静态代码块:static修饰的代码块,加载类加载
普通代码块:正常的运行的普通代码块
构造代码块:加大括号的代码块,在构造函数之前调用
同步代码块:synchronized修饰的代码块,只允许一个线程调用个
##3.Java命名规则:
1、 项目名,包名全部小写
2、 类名首字母大写,如果类名由多个单词组成,每个单词的首字母都要大写。
3、 变量名、方法名首字母小写,如果名称由多个单词组成,每个单词的首字母都要大写。
4、 常量名全部大写
5、所有命名规则必须遵循以下规则:
1)、名称只能由字母、数字、下划线、$符号组成
2)、不能以数字开头
3)、名称不能使用JAVA中的关键字。
4)、坚决不允许出现中文及拼音命名。
##4.零碎知识点
1>直接将对象打印到控制台结果是类的路径@十六进制数据(hashcode值)
一般情况下:我们所得hashcode的值就是在内存中的引用地址值
2>pdf2Doc:将PDF文件转化为doc文件,2代表的是to,4代替for
3>用于引用数据类型的时候,比较的是内存中引用的地址值
5>System.currentTimeMillis 获取当前时间(ms)
6>JDk的安装:
1安装路径不能出现中文和空格
2配置环境变量
JAVA_HOME:jdk的安装主目录
path(大小写根据个人电脑具体内容更改):添加的是jdk的bin目录与jre的bin目录中的应用写程序
CLASSPATH:.;类路径,简单来说就是jar包的路径
7>数组的复制
System.arraycopy(a,1,a1,0,4);
从a的下标1开始复制给a1,长度为0-4
8>垃圾,就是内存中某一块空间没有一个变量引用.垃圾回收:GC,java自行调度,程序员无法控制
##5. 类型、变量、方法、修饰符
###数据类型
基本数据类型:
整数类型;byte short int long
浮点数类型:float double
字符型:char
布尔型:boolean
基本数据类型和对应的包装类
基本类 包装类 基本类 包装类 基本类 包装类 基本类 包装类
char Character byet Byte long Long float Float
int Integer boolen Boolen double Double short Short
除int,char以外的其他基本类型的包装类为首字母大写
引用数据类型:
String,数组以及接口等,所有的类都是引用数据类型
String,StringBuff,StringBulider
速度:StringBuilder > StringBuffer > String
原因:String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。
线程安全:StringBuilder是线程不安全的,而StringBuffer是线程安全的
泛型:
泛型是JDK1.5出现的新特性,泛型是一种安全机制,使用泛型避免了强制类型转换。
###数组
一维数组定义:
//静态初始化数组:方法一
String cats[] = new String[] {
"Tom","Sam","Mimi"
};
//静态初始化数组:方法二
String dogs[] = {"Jimmy","Gougou","Doggy"};
//动态初始化数据
String books[] = new String[2];
books[0] = "Thinking in Java";
books[1] = "Effective Java";
二维数组定义:
int d[][] = new int[10][10];
int []d[] = new int[10][10];
int [][]d = new int[10][10];
###变量
成员变量定义在类中,称为字段,静态为类成员变量,动态为实例成员变量,除成员变量外的变量均为局部变量
成员变量有初始化值,局部变量初始化值需要自定义
各基本类型及其默认的初始化值
类型 默认值
byte int short long 0
float double 0.0
char null
boolen false
###方法
在java中,方法就是行为,一段代码能做的事情
1.方法只有调用才能执行其中的代码。
2.方法中的参数只是形式上的,关键是类型。参数名无所谓
###修饰符权限
修饰符 当前类 当前包 同一包子类 不同包子类 不同包不同子类
public公共 1 1 1 1 1
protected受保护 1 1 1 1 0
default默认 1 1 1 0 0
private私有 1 0 0 0 0
##6.重写与重载
###重写(Override)
定义:子类对父类的允许访问的方法的实现过程进行重新编写,返回值和形参都不能改变。
作用:
1.子类可以根据需要,定义特定于自己的行为。
2.子类能够根据需要实现父类的方法。
子类重写后的方法会在子类对象中首先被调用。
**规则** *两同两小一大*
1.两同
1>方法名相同参数
2>列表相同
2.两小
1>子类的返回值类型小于或等于父类的返回值类型
1)基本类型和voide必须相同
2)引用类型时,小于或等于
2>子类抛出的异常小于或等于父类的异常
3.一大
1>子类的访问权限大于或等于父类的访问权限
###重载(Overload)
定义:在一个类里面,方法名字相同,而参数不同,返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
**规则**
1.参数列表必须改变(参数个数或类型或顺序不一样);
2.返回值类型、访问修饰符、检查异常可以改变。
3.方法只能够在当前类或子类中被重载(基于继承)。
###重写与重载的区别
区别点: 重载方法 重写方法
参数列表 必须修改 一定不能修改
返回类型 可以修改 一定不能修改
异常 可以修改 可以减少或删除,一定不能抛出新的或者更广的异常
访问权限 可以修改 一定不能做更严格
##7.抽象类与接口
###抽象类
定义:同时具有抽象方法和固定方法的类可以定义为抽象类。
1.只有抽象类的非抽象子类可以创建对象。
2.抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
3.构造方法,类方法(用static修饰的方法)不能声明为抽象方法。
4.抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
###接口
定义:抽象方法的集合。
关键字:implements。
1.接口没有构造方法,不能用于实例化对象。
2.接口中所有的方法必须是抽象方法,默认public abstract修饰。所有变量必须为public static final 变量。
3.一个类可以实现多个接口。
**作用**
解决多继承问题
###抽象类与接口的区别
1.抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
2.抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final类型的。
3.接口中不能含有静态代码块以及静态方法(用static修饰的方法),而抽象类是可以有静态代码块和静态方法。
4.在接口中无成员变量,而抽象类中可有成员变量
##8.集合
Collection和Map,是集合框架的根接口。
Collection的子接口:
Set接口 ---实现类: HashSet、LinkedHashSet
set子接口:
SortedSet接口---实现类:TreeSet
List接口---实现类: LinkedList,Vector,ArrayList
Iterable(迭代器)——→Collection———→List、Set、Queue
比较器:
compareTo(Object o) 元素自身具备比较性
compare( Object o1, Object o2 ) 给容器传入比较器
###1.Collection
####1.1.List
特点:有序,可重复,长度可变
1)常用实现类:
1.ArrayList:数组实现,查询快,增删慢,轻量级;(线程不安全)
2.LinkedList:双向链表实现,增删快,查询慢 (线程不安全)
3.Vector:数组实现,重量级 (线程安全、使用少)
2).ArrayList在元素填满容器时会自动扩充容器大小的50%,而Vector则是100%,因此ArrayList更节省空间。
3).ArrayList自动扩充机制
实现机制:ArrayList.ensureCapacity(int minCapacity)
a.首先得到当前elementData属性的长度oldCapacity。
b.然后通过判断oldCapacity和minCapacity参数谁大来决定是否需要扩容,
c:IF.如果minCapacity大于oldCapacity,那么我们就对当前的List对象进行扩容。
c:Else 如果minCapacity不大于oldCapacity那么就不进行扩容。
d:扩容策略:
取(oldCapacity * 3)/2 + 1和minCapacity之间更大的那个。
然后使用数组拷贝的方法,把以前存放的数据转移到新的数组对象中
####1.2.Set
特点:无序(即取出顺序和储存顺序不同),不可重复
注:Java优先实现hashMap、TreeMap等Map集合,通过包装一个value为空的Map集合实现Set。
1)常用实现类:
1.HashSet:equals返回true,hashCode返回相同的整数;哈希表;存储的数据是无序的。
3.LinkedHashSet:维护着一个运行于所有条目的双重链接列表。存储的数据是有序的。
2)HashSet判断两个元素是否相同:
先要判断元素的hashCode值是否一致,只有在该值一致的情况下,才会判断equals方法,如果存储在HashSet中的两个对象hashCode方法的值相同equals方法返回的结果是true,那么HashSet认为这两个元素是相同元素,只存储一个(重复元素无法存入)。
###2.Map
特点:无序,key唯一(key设计要尽量简介)
Map的key存放方式类似于set,value存放方法类似于list。
1)常用实现类:HashMap、Hashtable ( 注意table是小写的t)
a.HashMap不是线程安全的;HashTable是线程安全的,其线程安全是通过Sychronize实现。
b.由于上述原因,HashMap效率高于HashTable。
c.HashMap的键可以为null,HashTable不可以。
d.多线程环境下,通常也不是用HashTable,因为效率低。HashMap配合Collections工具类使用实现线程安全。
e.同时还有ConcurrentHashMap可以选择,该类的线程安全是通过Lock的方式实现的,所以效率高于Hashtable。
2)HashMap扩容时需要生成一个新的HashMap将所有的key-value重新落桶一次(即重新put).
3)遍历时entryset遍历一次,其余两种情况遍历两次,所以entryset效率更高3
##9.I/O流
####1.流分类
1.基本流:字符流和字节流的最顶层流(1a+1b+2a+2b)
2.高级流:缓冲流(包括字节和字符缓冲流)、数据流、对象流
缓冲流:操作已有的流(一般为基本流),不直接操作文件。
把数据先写入缓冲区,等缓冲区满了,再把数据写到文件里。
flush():将缓存中内容传出并清空缓存区
close():将缓存中内容传出,关闭文件流。保证数据传输完整
####2.I/O类型:
1.字符流:
a.Reader
BufferedReader(缓冲流)(解析字符文件流FileReader)
InputStreamReader(转换流)
FileReader(文件流)
b.Writer
BufferedWrite(缓冲流)(解析字符文件流FileWriter)
OutputStreamWrite(转换流)
FileWrite(文件流)
PrintWriter(打印流)
2.字节流:
a.InputStream(读入)
FileInputStream(文件流)
FilterInputStream:通过装饰者模式来实现对InputSteream的改造
DataInputStream(可直接从文件中读出java基本类型和String类型数据)
BufferedInputStream(缓冲流)(解析字节文件流FileInputStream)
b.OutputStream(写出)
FileOutputStream(文件流)(默认构造方法是直接覆盖掉原来的文件。不存在则创建空文件
构造方法:FileOutputStream(File file, boolean append)
如果后面的append为true的时候就是追加到尾部而不是直接覆盖了。)
FilterOutputStream:通过装饰者模式来实现对outputSteream的改造
DataOutputStream(可直接向文件中写入java基本类型和String类型数据)
BufferOutputStream(缓冲流)(解析字节文件流FileOutputStream)
PrintStream(打印流-输出)
3.对象流:使对象持久化,需要对象实现 Serializable(可系列化的)接口----涉及序列化、反序列化
ObjectInputStream / ObjectOutputStream
4.随机存取文件流
RandomAccessFile(读写是基于指针当前位置进行的)
RandomAccessFile raf = new RandomAccessFile("demo.dat", "rw");
第二个参数为文件的操作权限,r为只读,rw为读写。权限不足则抛出异常
void write(byte[] d ,int offerset ,int len)该方法可以预防复制文件变大的问题
####3.File类:用于表示硬盘上的一个文件或者目录
作用:
1.访问文件或者目录的属性信息
2.操作文件或者目录(创建和删除)
3.查看目录中的子项,但是不能访问文件的内容
####4.编码格式
字符是一个16为整数,文件中的数据byte(8位)为单位。如果char类型写入文件,必须拆分为已byte为单位的数据.字符的拆分有多重方式(即编码格式):UTF-8 GBK
1.UTF16-BE:等符编码
将16位的char型数据一分为二,英文2个byte,中文也是2个byte。
优点:定长两个字节
缺点:英文冗余100%
2.UTF-8
编号小的1字节编码(英文和符号)
编号居中的2字节编码(128-2000+)
编号稍大的3字节编码(2000+-6555涵盖了全部的中文)
编号更大的4字节编码(6555-1000000+)
优点:支持10万+文字 英文编码 万国码
缺点:中韩日等语言冗余50%
3.GBK
编号小的英文 1字节 128个
编号大的中文 2字节
优点:中英混合编码最优
缺点:范围小,支持语言少
##10.异常
####1.Throwable,Error,和Exception
Throwable是java异常结构的父类,
Error表示java运行时环境出现的错误。
Excption表示由于网络故障,文件损坏,设备错误,用户输入非法等情况导致的异常。
####2.try-catch
a.try{}语句中包含可能会发生异常的语句,在运行过程中,该代码可能会产生并抛出一种或者几种类型的异常对象,他后面的catch分别对这些异常进行处理。try必须跟一个catch或者一个finally。try代码块中出现异常后会寻找相应的catch,执行流跳转到最近的匹配的异常处理catch代码块去执行,异常被处理完后,执行流会接着在“处理了这个异常的catch代码块”后面接着执行。这叫做终结式异常处理模式。
b.catch中声明了异常对象,在catch中可使用这个对象的一些方法获取信息。
c.finally代码块
一般放在try-catch后面。
finally块不管异常是否发生,只要对应的try执行了,则它一定也执行。
只有一种方法让finally块不执行:System.exit()。
因此finally块通常用来做资源释放操作:关闭文件,关闭数据库连接等等。
良好的编程习惯是:在try块中打开资源,在finally块中清理释放这些资源。
在 try块中即便有return,break,continue等改变执行流的语句,finally也会执行。
####3.非检测异常与可检测异常
a.可检测异常:必须处理的异常,不处理则不允许编译
b.非检测异常:RuntimeExcption(运行时异常)
####4.自定义异常
a.定义:程序运行到一个满足语法需要(和程序无关),但是不满足业务逻辑时,可以直接创建一个继承Excption类的自定义异常类
b.自定义异常的构造方法应该包含一下内容:
一个无参构造函数
一个带有String参数的构造函数,并传递给父类的构造函数。
一个带有String参数和Throwable参数,并都传递给父类构造函数
一个带有Throwable 参数的构造函数,并传递给父类的构造函数。
c.当程序执行遇见错误,但是该异常不是应该由当前代码来处理,应当抛给调用者
d.通常一个方法使用throw抛出异常需要用throws来表明异常的类型 告诉方法的调用者需要处理,在方法的逻辑中出现自定义错误的时候throw出这个异常
public void setAge(int age) throws illegalAgeException{
this.age = age;
if(age<0||age>150) {
throw new illegalAgeException("不符合人类年龄正常范围");
}
}
####5.使用自定义异常的子类与父类的关系
a.可以不再声明抛出任何异常
b.可以抛出父类抛出的部分异常
c.不能抛出与父类抛出的异常无继承关系的异常
d.不能抛出父类抛出异常的父类异常
e.可以抛出父类抛出的异常的子类异常
##11.线程
####1.定义与来源:
进程是操作系统中运行的一个任务,是一块包含某些资源的内存区域。
定义:进程中所包含的一个或者多个执行单元叫做线程
线程只能归属与一个进程,当操作系统创建一个进程以后会自动申请一个名为主线程或者首要线程的线程
线程一个进程的一个顺序执行流(也被叫做轻负荷进程)
####2.创建线程的方法
a.继承Thread类并重写run()方法
a.run()方法内是线程执行的内容
b.start()是线程启动方法
c.不会直接调用run()方法,该方法是在线程启动起来以后,第一次份分配时间片自动调用。
优缺点:Thread类本身包含了很多的线程操作方法,但是限制了子类只能继承多线程类,实现资源共享时需要创建父类对象并调用父类方法。
b.实现Runnable接口
class MyRunnable implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 1000; i++) {
System.out.println("who ara you");
}
}
}
优点:解决了继承Thread类的局限性。
1.单独定义任务,由于任务是实现接口,java中接口是多实现的,所以不会造成继承冲突。可以实现资源共享.
2.由于单独定义任务,所以任务和线程之间没有必然的耦合关系。
缺点:由于接口本身没有没有start方法,所以需要创建一个Thread对象来启动start.
c.使用匿名内部类形式创建线程
//方式一
Thread t1 = new Thread() {
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("how old are you?");
}
}
};
//方式二
Runnable runn = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("who are you?");
}
}
};
线程提供了一个currentThread方法用来获取运行方法的线程。
####3.线程生命周期
a.创建:程序每new一个线程对象,就是新建
b.就绪:当我们调用start方法(调用start不一定就是在执行)
c.运行:当线程抢到资源开始执行里面代码的时候
d.堵塞:(逻辑性错误),(人工堵塞)当前线程抢占到资源进入休眠
e.死亡:(正常死亡(运行后销毁))当线程执行完成,非正常死亡(程序崩溃))出现异常与错误
####4.Sleep 和wait 的区别:
两者是不同类提供的方法
线程提供了一个静态方法sleep(long ms),该方法用于试运行该方法的线程阻塞指定毫秒数,当阻塞超时后,线程会回到runnable状态,等待再次分配时间片后继续运行.Sleep只能通过设置时间自动唤醒.
Wait可以通过notifyall 与 notify 进行人工唤醒
####5.线程分配
线程调度会尽可能均匀的将线程分配给并发运行的线程,对于我们而言,线程调度将时间片分配给哪个线程,分配的时间长短我们都不可控制
对于线程而言,只能被动的等待分配时间片,不能主动获取。但是我们可以通过改变线程的优先级来改变时间片的长度,理论上,优先级越高,获取CPU次数越多
####6.守护线程
当一个进程中的所有前台线程结束时,进程结束,所以无论进程中的守护线程是否在运行,都要被强制中断