Java笔记 | Java基础
记录一下Java基础中我觉得需要留意的知识点。
- Java初识
- Java数据类型
- Java中的特殊进制表示
八进制:以0开头,包含0-7的数字
十六进制:以0x或0X开头,包含0-9、a-f、A-F
- Java二维数组
三种声明格式:
//声明int类型的二维数组
int[][] intArray;
//声明float类型的二维数组
float floatArray[][];
//声明double类型的二维数组
double[] doubleArray[];
二维数组在创建时可以只指定行数,且每行的列数可以不同:
//只指定行数
floatArray = new float[3][];
//每行相当于一个一维数组,需要创建,列数可以不相等
floatArray[0] = new float[3];//第一行有3列
floatArray[1] = new float[4];//第二行有4列
floatArray[2] = new float[5];//第三行有5列
- Java的构造方法
构造方法与类同名且没有返回值,只能在对象实例化的时候被调用。
如果未定义构造方法,则系统自动添加一个无参的构造方法。如果存在构造方法,则不论该构造方法是否为无参,都不会再添加无参的构造方法。
- package
必须放在源文件第一行,每个源文件只能有一个package语句。
- static
只能+属性or方法,不能+类。
随类的加载而产生,至类的销毁而回收。
静态方法中不能直接调用同一个类中的非静态成员。
- Java继承(extends)
继承后的初始化顺序:父类静态->子类静态->父类构造->子类构造
- super与this
super是父类对象的引用,this是当前类对象的引用。
都不能在静态方法中使用。
在构造方法中,super和this不能同时出现。
- 重载与重写
重载Overload,编译多态性:
--在同一个类中
--方法名相同,参数列表不同
--返回类型和访问修饰符可同可不同
重写Override,运行多态性:
--在子类中
--方法名相同,参数列表相同,返回类型相同或者是其子类类型
--访问修饰符的范围需要大于等于父类
- Java访问修饰符
访问修饰符 | 本类 | 本包 | 子类 | 其他 |
---|---|---|---|---|
private | 1 | |||
默认 | 1 | 1 | ||
protected | 1 | 1 | 1 | |
public | 1 | 1 | 1 | 1 |
- Object类的常用方法
toString():返回当前对象的相关信息,return String
equals():比较两个对象是否为同一个对象,return Boolean
hashCode():返回该对象的哈希代码值
getClass():获取当前对象的类,return Class
- final
final类不能被继承,即没有子类。
final方法可以被继承,不能被重写。不能用final修饰构造方法。
final变量在赋值后不能被修改。
--如果是方法中的局部变量,则在使用前赋值即可。
--如果是类中的成员变量,则必须在定义时或构造方法中进行初始化。
--如果变量是基本数据类型,则在赋值后不能被修改。
--如果变量是引用数据类型,则其引用指向不能被修改,被指向的对象可以被修改。
static final变量在赋值后不能被修改,且可以用类直接访问or调用。
static final方法不能被重写,且可以用类直接访问or调用。
- 多态
编译时多态:即方法重载。
运行时多态:Java运行时系统根据调用该方法的实例的类型来选择调用的方法。(包含方法重写)
向上转型:父类引用指向子类实例。(自动转型、隐式转型)
--当一个子类对象向上转型为父类类型后就被当成了父类对象
--只能调用子类重写或继承该父类的方法,不能调用子类自己的方法。
--同时也不能重写父类的静态方法。
向下转型:子类引用指向父类实例。(强制类型转换)
--向下转型后可以调用子类独有的方法。
--兄弟类之间不能进行强制类型转换。
--instanceof用来判断某对象是否为某类的实例。
- abstract
抽象类:所有的对象都是通过类来描述的,但并不是所有的类都是用来描述对象的。当一个类中没有包含足够的信息以描绘一个具体的对象时,这样的类都是抽象类。
抽象类不能实例化,只能作为其他类的父类。
抽象类的父类可以是非抽象类。
包含抽象方法的类只能是抽象类。抽象类不一定有抽象方法。抽象类的子类如果没有实现其所有抽象方法,那么子类也只能是抽象类。
抽象类不能用final修饰。因为被final修饰的类不能被继承,而抽象类需要被继承。
抽象方法只有方法头。
抽象方法不能用static、final或private修饰。因为抽象方法需要被重写,而static、final或private方法不能被重写。
- interface
接口:定义类所需要遵守的规范,规定类中必须要实现的方法。
--接口的常量默认添加static final
--接口的抽象方法默认添加abstract
实现接口用implements关键字,继承类用extends关键字
- 接口与抽象类
相同点:
--都可以包含抽象方法。
--都不能被实例化。
--都是引用数据类型。
不同点:
--一个类可以实现多个接口,但只能继承一个抽象类。
--接口的方法默认为抽象方法,接口的default方法和static方法可以添加方法体;抽象类的方法默认为普通方法。
--接口只能定义静态常量属性,且必须在定义时初始化;抽象类可以定义实例属性和静态常量属性。
- 异常的分类
Error是程序无法处理的错误,表示运行程序中较严重的问题,大多数表示代码运行时JVM出现的问题。这些错误是不可查的,因为它们在程序的控制和处理能力之外。我们编写程序时不需要关心这类异常。
Exception是程序可以处理的异常。异常处理通常指针对这类异常的处理。包括checked exception和unchecked exception。
RuntimeException及其子类属于unchecked exception,编译器不要求强制处理。除此之外的其他Exception都属于checked exception。
- 异常处理机制
抛出异常(throw、throws):
--当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统。
--异常对象中包含了异常类型和异常出现时的程序状态等异常信息。
--运行时系统负责寻找处理异常的代码并执行。
捕获异常(try、catch):
--方法抛出异常之后,运行时系统将转为寻找合适的异常处理器。
--运行时系统从发生异常的方法开始,依次回查调用栈中的方法,当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适的异常处理器。
--当运行时系统遍历调用栈而未找到合适的异常处理器,则运行时系统终止。同时意味着Java程序的终止。
--Java规定对于可查异常必须捕捉,或者声明抛出。允许忽略运行时异常和错误。
- 异常处理语法
try:执行可能产生异常的代码。
catch:捕获异常。
--catch可以有多个也可以没有。如果没有catch,则try后面必须跟finally。
--只执行第一个与异常类型匹配的catch语句。所以排列时应该先子类后父类。
finally:无论是否发生异常都执行的代码。
throws:在方法头中声明可能要抛出的异常。
throw:在代码中手动抛出异常。
--在try...catch中包含throw语句,自己抛自己处理。
--使用throws在方法头声明抛出的异常类型,谁用谁处理。调用者可以自己处理,也可以继续上抛与throw对象相同的类型或者其父类。
- 常见异常
Exception:异常层次结构的父类。
ArithmeticException:算数异常,如以0作除数。
ArrayIndexOutOfBoundsException:数组下标越界。
NullPointerException:空指针异常,尝试访问null对象成员。
ClassNotFoundException:不能加载所需的类。
IlligalArgumentException:方法接收到非法参数。
ClassCastException:对象强制类型转换出错。
NumberFormatException:数字格式转换异常,如把“abc”转为数字。
- 包装类
Byte byte
Short short
Integer int
Long long
Float float
Double double
Character char
Boolean boolean
BigInteger 支持任意精度的整数
BigDecimal 支持任意精度的小数
基本数据类型和包装类的区别:
--声明方式不同。基本数据类型直接创建;包装类需要new来创建
--存储位置不同。基本数据类型直接在栈中存储变量的值便于高效存取;包装类通过引用指向实例,实例保存在堆中。
--初始值不同。int的初始值为0,boolean的初始值为false,char的初始值为\u0000;而包装类的初始值为null。
--使用方式不同。例如与集合共同使用时只能使用包装类。
--基本数据类型不是对象。
装箱:把基本数据类型转为包装类
int t1 = 2;
//自动装箱
Integer t2 = t1;
//手动装箱
Integer t3 = new Integer(t1);
拆箱:把包装类转为基本数据类型
//自动拆箱
int t4 = t2;
//手动拆箱
int t5 = t2.intValue();
- Integer的对象池机制
如果Integer类的参数满足-128<参数<127,则会从对象池中判断是否存在这样的对象,如果有则直接用,没有就会创建一个。如果超出该范围,则无论如何都会创建一个新的对象。包装类中除了Float和Double外都有对象池机制。
- equals和“==”的区别
“==”对于基本数据类型比较的是他们的值,对于引用数据类型比较的是堆内存地址。
equals默认是比较对象的内存地址,在一些类库中该方法被重写为比较内容。
在String的比较中,“==”比较的是两个字符串的内存地址,equals比较的是两个字符串的内容。
在常量池中,保存直接定义的字符串。在栈中保存变量名。在堆中保存new的String对象。
如果equals返回true,则hashCode()结果必相等。如果hashCode()结果不相等,则equals必为false。
- 字符串的装箱与拆箱
装箱:toString()
拆箱:parseXXX()、valueOf()
//基本数据类型转换为字符串
int t1 = 2;
String t2 = Integer.toString(t1);
//字符串转换为基本数据类型
//1、包装类的parse
int t3 = Integer.parseInt(t2);
//2、包装类的valueOf
//先将字符串转换为包装类,再通过自动拆箱完成基本类型转换
int t4 = Integer.valueOf(t2);
- 字符串的常用方法
int length():字符串长度
int indexOf(int ch):查找第一次出现的位置
int indexOf(String str)
int lastIndexOf(int ch):查找最后一次出现的位置
int lastIndexOf(String str)
String substring(int beginIndex):获取子字符串
String substring(int beginIndex, int endIndex)
String trim():去空格
boolean equals(Object obj)
String toLowerCase():转小写
String toUpperCase():转大写
char charAt(int index):获取指定位置的字符
String[] split(String regex, int limit):分割为子字符串
byte[] getBytes():将字符串转为byte数组
String concat(String str):连接字符串
String format(String str):格式化(%f-浮点,%d-整型,%s-字符串)
String replace(char oldChar, char newChar):替换字符串
- String、StringBuilder、StringBuffer
String具有不可变性。String对象一旦创建则不能修改,是不可变的。所谓修改其实是创建了新的对象,所指向的内存空间不变。当用String频繁操作字符串时会产生很多中间变量和废弃数据。
StringBuilder性能略高,但不是线程安全的,不适合于多线程。
StringBuffer是线程安全的,可以用于多线程。
- StringBuilder的常用方法
append():在末尾添加内容
insert():在指定位置添加内容
delete():删除指定位置的内容
replace():替换指定位置的内容
- 迭代器(Iterator)
Iterator接口以统一的方式对各种集合元素进行遍历。
常用方法:
hasNext():判断集合是否还有下一个元素。
next():返回下一个元素。
remove():从集合中删除返回的元素。
import java.util.ArrayList;
import java.util.Iterator;
public class RunoobTest {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(12);
numbers.add(8);
numbers.add(2);
numbers.add(23);
Iterator<Integer> it = numbers.iterator();
while(it.hasNext()) {
Integer i = it.next();
if(i < 10) {
it.remove(); // 删除小于 10 的元素
}
}
System.out.println(numbers);
}
}
- Comparator
强行对某个对象进行整体排序的比较函数。
可以将Comparator传递给sort方法。
int compare(T o1, T o2):比较用来排序的两个参数,o1<o2返回负整数,o1==o2返回0,o1>o2返回正整数。
定义:
import java.util.Comparator;
public class AgeComparator implements Comparator<Cat> {
@Override
public int compare(Cat o1, Cat o2) {
// 按年龄降序排序
int age1 = o1.getMonth();
int age2 = o2.getMonth();
return age2 - age1;
}
}
使用:
Collections.sort(catList, new AgeComparator());
- Comparable
强行对实现它的每个类的对象进行整体排序。
称为类的自然排序,类的compareTo方法称为类的自然比较方法。
int compareTo(T o):该对象小于、等于、大于指定对象则分别返回负整数、0、正整数。
- 泛型
在Java增加泛型之前,泛型程序设计使用继承来实现。这种方法需要强制转换,且向集合中添加任意类型的对象存在风险。
变量声明的类型必须匹配传递给实际对象的类型。
Java SE7及后续版本中构造方法可以省略泛型类型。
- File类
创建File对象:
//方法1
File file1=new File("c:\\io\\score.txt");
//方法2
File file1=new File("c:","io\\score.txt");
//方法3
File file=new File("c:");
File file1=new File(file,"io\\score.txt");
isDirectory():是否为目录
isFile():是否为文件
exists():是否存在
mkdirs():创建多级目录
createNewFile():创建文件
isAbsolute():是否为绝对路径
getPath():获取相对路径
getAbsolutePath():获取绝对路径
getName():获取文件名
- 字节流
继承InputStream、OutputStream
FileInputStream、FileOutputStream
fis.read():读取一个字节
fos.write():写入一个字节
close():关闭流并释放系统资源
BufferInputStream、BufferOutputStream
bos.flush():强制从缓冲区写入文件
- 字符流
继承Reader、Writer
字节字符转换流:InputStreamReader、OutputStreamWriter
- 对象序列化
序列化是一种将对象转换为一连串的字节的过程,用于解决在对对象流进行读写操作时引发的问题。
序列化可以将对象的状态写在流里进行网络传输,并在需要时把流取出来重新构造一个相同的对象。
要实现序列化的类必须实现Serializable接口。
反序列化是根据字节流中保存的对象状态及描述信息重建对象。
使用场景:将对象保存至数据库中;使用套接字在网络上传输对象。
写:
ObjectOutputStream oos = new ObjectOutputStream(fos);
// 将Goods对象信息写入文件
oos.writeObject(goods1);//写————序列化
oos.writeBoolean(true);
oos.flush();
读:
ObjectInputStream ois = new ObjectInputStream(fis);
//读对象信息
//读的顺序和写的顺序是一样的
try {
Goods goods = (Goods) ois.readObject();//读————反序列化
System.out.println(goods);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}