目录
多态机制
有参构造方法和无参构造方法
复制对象和复制引用
浅拷贝和深拷贝
&和&&
break和continue
equals和hashcode
equals和==
String类
方法重载(overload)和重写(override)
抽象类和接口的异同
静态变量和实例变量
异常(exception)
error和exception
throw和throws
final、finally和finalize
“+”/append()连接字符串
int、Integer之间的比较
字节流--->字符流
字节流和字符流的区别
集合安全性
List三个子类
Map常见子类
Set常见子类
List、Map、Set
多线程共享数据方式
线程池
wait和sleep方法
静态嵌套类和内部类
小点
靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动
态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变
量的类型中定义的方法
编写类时,默认有无参构造方法。
添加有参或无参构造方法后,默认的无参构造会失效---------------->so 仅添加有参构造方法后,再调用无参构造方法编译报错。
Person p = new Person(11);
Person p1 = p;------------------------->复制引用,地址相同
Person p2 = (Person)p.clone();------------------>复制对象,地址不同
对象拷贝时,成员变量是引用数据类型如String时:
仅拷贝引用值--------->浅拷贝-------------------->so 改变新拷贝对象的值时,原先的对象也会改变。
创建新的对象,将新的对象的引用值赋给新拷贝的对象------>深拷贝
看图可知:clone复制对象后,新对象的其他实体类对象的地址和原对象中该实体类对象的地址相同--------->so 浅拷贝
-------------> 要实现深拷贝时,该对象实现clone方法,该对象引用的其他对象也要实现clone方法。
代码即:
//1.在被引用的对象中也添加clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
//2.在原对象中添加clone方法时,将被引用对象也clone一次
//Person指原对象,Addr是被引用的实体对象
@Override
protected Object clone() throws CloneNotSupportedException {
Person newPerson = (Person) super.clone();
newPerson.addr = (Addr)addr.clone();
return newPerson;
}
&:按位与、逻辑与。------------>执行所有判断条件。
&&:短路与。------------> a&&b , if a == false , then 不进行b的运算。
注:I 和 II 类似。
break:跳出循环。continue:执行下一轮循环。
两个对象的equals相等则hashcode肯定相等,hashcode相等equals不一定相等。
equals方法满足:自反性、对称性、传递性和一致性。
重写equals时要重写hashCode-具体见 https://blog.csdn.net/u012557538/article/details/89861552
前者是方法后者是运算符
equals():比较内容是否相等
equals是先比较地址值,不相等再逐个比较字符
==:基本数据类型比较数值是都相等,引用数据类型比较对象的地址值是否相等
是final类,不可被继承,不可被修改--------->内存开销
注:StringBuffer类和StringBuilder类允许修改。StringBuilder单线程,没有被synchronized修饰,效率比StringBuffer高。单线程用StringBuilder,多线程用StringBuffer
重载和重写都是实现多态的方式,重载实现编译多态性,重写实现运行多态性。重载发生在一个类中,重写发生在子类和父类中。重写时子类不能比父类被重写方法声明更多的异常(里氏代换原则)。
重载:方法名一致,参数列表中参数顺序、类型、个数不同。对方法返回类型无要求,可抛出不同异常,可有不同修饰符。
重写:参数列表和返回类型必须与被重写方法一致。构造方法、声明为final的方法、声明为static的方法都不能被重写。重写方法不能比被重写方法访问权限更低。重写方法不能抛出任何非强制性异常。
注:函数不能根据返回类型来区分重载,因为调用时不能指定类型信息,编译器不知道要调用哪个函数。
抽象类:可定义构造器、可由抽象方法和具体方法、接口中成员都是public类型的、可定义成员变量、有抽象方法的类必须被声明为抽象类,而抽象类中未必有抽象方法、抽象类中可包含静态方法、一个类只能继承一个抽象类。
接口:不能定义构造器、方法全是抽象方法、成员类型无要求、定义的成员变量实际上都是常量、不能有静态方法、一个类可以实现多个接口。
同:都不能实例化、可以将抽象类和接口类型作为引用类型、一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部实现,否则该类仍然需要被声明为抽象类。
静态变量:static修饰的变量,类变量属于类,不属于类的对象,一个类不管创建多少对象,静态变量在内存中有且仅有一个拷贝。
实例变量:必须依存于某一实例,先创建对象然后通过对象访问。
静态变量可以实现让多个对象共享内存。
注:静态方法和实例对象,前者是类的成员,后者是对象的成员。
静态方法---->没有对象------>没有“对象所属类型”---->无法override
编译时异常(强制性异常)和运行时异常(非强制性异常)
注:try…catch块中,遇到return,如果有finally就必须先执行完finally代码块的代码再返回值。即 try/catch中有return,finally里也有return,最终返回的是finally里的return。如果try/catch里没有return,则正常执行顺序为try/catch然后是finally。
父类都是throwable
error类一般指与虚拟机相关的错误,仅靠程序本身无法恢复和预防,遇到时建议程序终止。
exception类表示程序可以处理的异常,可以捕获且可能恢复,遇到时应尽快处理。
throw:语句用在方法体内,由方法体内的语句处理。抛出一个异常实例,执行throw一定抛出某种异常。
throws:用在方法声明后面,如果抛出异常由方法的调用者来处理。表示异常出现的可能性,和异常的类型,不一定会发生。
final:声明属性、方法和类---------->属性不可变、方法不可覆盖、类不可继承
finally:异常处理语句结构的一部分,表示总是执行
finalize:Object 类的一个方法,在垃圾回收器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,该方法更像是一个对象生命周期的临终方法,当该方法被系统调用则代表该对象即将“死亡”。但是需要注意的是,我们主动行为上去调用该方法并不会导致该对象“死亡”,这是一个被动的方法(其实就是回调方法),不需要我们调用。
使用“+”运算符和调用StringBuffer/StringBuilder对象的 append 方法连接字符串,实际上编译后都是使用的StringBuffer/StringBuilder。
效果是一样的,如果拼接的字符串不多,可以使用“+”,效率不一样,拼接字符串多的话,后者效率明显要高。
注:“+”和append()不要混着用,会创建更多的SB对象。
Integer a = 11; //int被封装为Integer对象,通过Integer.valueOf()
int b = 11;
Integer c = new Integer(11);
System.out.println(a == b); //比较内容大小 T
System.out.println(a == c); //比较内存地址 F
System.out.println(b == c); //比较内容大小 T
字节流:InputStream、OutputStream
字符流:Reader、Writer
字节输入流转字符输入流通过InputStreamReader实现
//字节输入流转字符输入流
InputStream in = System.in; //字节流
BufferedReader br = null; //字符流
BufferedWriter bw = null;
try {
br = new BufferedReader(new InputStreamReader(in));
bw = new BufferedWriter(new FileWriter("E:/a.txt"));
String line = null;
while ((line = br.readLine()) != null) {
if("exit".equals(line)){
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bw != null) {
bw.close();
}
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
字节输出流转字符流输出流通过OutputStreamReader实现
//字节输出流转字符输出流
OutputStream os = System.out; //字节输出流
BufferedReader br = null; //字符流
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new OutputStreamWriter(os));
br = new BufferedReader(new FileReader("E:/a.txt"));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (bw != null) {
bw.close();
}
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
字节流----->读到一个字节就返回一个字节。可以处理所有类型数据。主要操作byte数据。处理单元为1个字节。
字符流------>使用字节流读到一个或多个字节时先去查指定的编码表,将查到的字符返回。只能处理字符流数据。处理的单元为2个字节的Unicode字符。
纯文本数据优先使用字符流,其他都用字节流。
ArrayList、HashMap、HashSet中方法都没有加锁,线程不安全。------>Collections提供API让他们变成安全的--eg:Collections.synchronizedList(list);
HashTable、Vector线程安全。
ArrayList:底层是数组,查询快、增删慢。
LinkedList:底层是链表,增删快、查询慢。
voctor:底层是数组,线程安全,增删慢、查询慢。
HashMap:基于Map接口,非线程安全、高校、支持Null值和Null键
HashTable:线程安全、低效、不支持Null值和Null键
LinkedHashMap:HashMap的子类,保存记录的插入顺序
TreeMap:有序、默认键值升序
HashSet:打印结果和插入顺序无关
LinkedHashSet:打印结果和插入顺序相同
TreeSet:按值升序/降序输出
List:存储单列数据的集合、有序、允许重复
Set:存储单列数据的集合、无序、不重复
Map:存储键值对的集合、无序、不重复
多线程行为一致,共同操作一个数据源
多线程行为不一致,共同操作一个数据源
线程池就是事先将多个线程对象放到一个容器中,当使用的时候就不用 new 线程而是直接去池中拿线程即可,节省了开辟子线程的时间,提高的代码执行效率。
限制系统中执行线程的数量。减少创建和销毁线程的次数,每个线程都能重复利用执行多个任务。使用线程池可以根据系统的承受能力调整线程池中工作线程的数目,防止死机。----------->降低资源消耗、提高响应速度、提高线程的可管理性。
wait 通常被用于线程间交互, sleep 通常被用于暂停执行。
wait()和notify()是Object类的,sleep()是Thread类的
wait方法会把当前的对象锁释放,让其他线程访问这个对象锁。而sleep()方法只是把当前线程进入等待状态,等时间到了之后会继续执行该线程。
静态嵌套类:是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。
内部类:需要在外部类实例化后才能实例化。
注:静态方法中没有外部类的对象,无法创建非静态内部类对象。如下图,会报错。
java中方法调用只支持参数的值传递
数组没有length()方法,而是length属性。String有length()方法。
ArrayList内部用Object[]实现