文章目录
面向对象的理解
- 在我理解,面向对象是向现实世界模型的自然延伸,这是一种
“万物皆对象”
的编程思想。在现实生活中的任何物体都可以归为一类事物,而每一个个体都是一类事物的实例。面向对象的编程是以对象为中心,以消息为驱动,所以程序=对象+消息。
面向对象有三大特性,封装
、继承
、多态
。
- 封装就是将一类事物的属性和行为抽象成一个类,使
其属性私有化,行为公开化
,提高了数据的隐秘性的同时,使代码模块化。这样做使得代码的复用性更高。 - 继承则是进一步将一类事物共有的属性和行为抽象成一个父类,而每一个子类是一个特殊的父类–有父类的行为和属性,也有自己特有的行为和属性。这样做扩展了已存在的代码块,进一步
提高了代码的复用性。
- 多态指得是一个类的多种形态,简单来说,就是允许父类引用(或接口)指向子类(或实现类)对象。提高程序的扩展力,降低程序的耦合度。
类型和类型之间的关系
- is a (继承):猫是个动物
- has a(关联):我有一支笔,调用对象。
- like a(实现):厨师像个菜单,行为抽象–>接口。
访问控制修饰符
Object方法
- equals: 默认比较内存地址。Stirng重写比较的是内容。
- toString: 默认返回对象的字符串表示形式,Stirng返回对象本身。
- finalize: 垃圾回收时机,JVM调用。
- getClass: 表示运行时的类。
- clone: 返回一个对象的拷贝。
- hashCode: 默认返回对象的哈希码值,Stirng只要字符串所在的堆空间相同,返回的哈希码也相同。Integer类
返回自己的值
。 - ==: 基本类型比较值,引用类型比较内存地址。
数组
- 是引用数据类型
- 带有
length属性
! - 长度确认不可改变。
- 要求元素统一
- 首元素为数组的内存地址
下标从0开始,长度从1开始!!!
- 数组是个连续空间,不适合存储大对象
- 数组
扩容机制是创建个大数组
,把数据拷贝过去。因为长度不可变。
浅拷贝和深拷贝
深拷贝和浅拷贝都是对象拷贝。
- 假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。
String类常用API
- contains: 判断是否包含。
- startsWith: 判断字符串是否以某个子字符串开始
- endsWith: 是否以某个子字符串结尾。
- getBytes: 转换成字节数组,指定编码返回。
- indexOf: 判断第一次出现的下标
- lastIndexOf: 判断最后一次出现的下标
- isEmpty: 是空吗?
- length: 获取长度,是方法。数组是属性。
- replace: 替换字符串
- split: 分割字符串,返回字节数组
- subString: 截取字符串,不包含尾数。
- toCharArray: 转换成字节数组
- trim: 去除前后空白
- valueOf:转换字符串
装箱拆箱
- Java中为了提高程序的执行效率,将
-128到127之间的所有包装对象提前创建好
,放到了一个方法区的“整数型常量池
”当中了,目的是只要用这个区间的数据不需要再new了,直接从整数型常量池当中取出来。 - 装箱:将值类型转换成引用类型的过程。
- 拆箱:将引用类型转换成值类型的过程。
- 装箱生成全新的引用会导致效率有所降低,所以要避免自动装箱。
异常
异常的作用是增强程序的健壮性。
- 异常是以类的形式存在着的。
- 所有异常都发生在运行阶段。
- 错误不能处理,编译异常必须处理,运行时异常可以不处理。
- 异常没有捕捉会抛给上级处理。
- finally子句中的代码是最后执行的,并且是一定会执行的。
- 可以有多个catch, 按异常从小到大。
常见面试题:
public static int m(){
int i = 100;
try{
return i;
}finally{
i++;
} //结果是100 因为方法自上而下的执行,i已经先返回了拿到了就算后面修改返回的也是100
集合的原理
Collection
Map
怎么保证集合的线程安全?
Collections.synchronizedList(List) 将线程不安全的List,返回线程安全的List
Collections.synchronizedCollection(Collection) 将线程不安全的Collection,返回线程安全的Collection
Collections.synchronizedMap(Map) 将线程不安全的Map,返回线程安全的Map
Collections.synchronizedSet(Set) 将线程不安全的Set,返回线程安全的Set
IO流
IO可以完成硬盘文件的读和写。
io流分类:
- 输入流(读):读取硬盘上的文件
- 输出流(写):对硬盘的文件进行添加,修改。
- 字符流:按字符读,只能读取文本,在文本领域效率高。
- 字节流:这种流是万能的可以读取任意的文件,'中’字符占用2字节。
按流的处理位置可分为节点流和包装流。
- 节点流:当一个流的构造方法中需要一个流的时候,被穿进去的流称为节点流
FileInputStream
。 - 处理流:对已存在的流的连接和封装,实现更为丰富的流数据处理,处理流的构造方法必需其他的流对象参数。如
BufferedReader
。
public static void main(String[] args) throws IOException {
FileReader reader = new FileReader("abc.text"); //节点流
BufferedReader f = new BufferedReader(reader); //处理流
System.out.println(f.readLine()); //读一行
}
注意:
- 以
stream
结尾的都是字节流。以“Reader/Writer
”结尾的都是字符流。 - 使用完流要
及时关闭
close(),不然会耗费很多资源。 - 所有输出流都实现了
java.io.Flushable
接口都是可刷新的,每次使用记得调用flush()
方法刷新管道将剩余的数据强行输出完,如果不刷新可能会导致数据丢失。
序列化&反序列化
- 序列化:把Java对象转换为字节序列的过程。
- 反序列化:把字节序列恢复为Java对象的过程。
对象的序列化主要有两种用途:
- 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;(持久化对象)
- 在网络上传送对象的字节序列。(网络传输对象)
使用方式:
- 必须实现Serializable接口(里面没有任何实现,只是起到一种标志性的作用)
JVM识别
到会特殊照顾
自动生成个随机版本号
。 - 不想序列化的字段可以使用
transient
修饰。 - 手动设置序列化版本号,让版本号固定不变。自动的版本号是不能修改的,每次序列化都会重新设置一个版本号,当
反序列时比较对不上就会报错
。
快速绑定资源文件
ResourceBundle bundle = ResourceBundle.getBundle("com/bjpowernode/test");
//这个文件必须是以.properties结尾。
反射
Class.forName():
加载类的对象。newInstance():
获取类的实例。getFieId():
获取成员变量,不能直接得到私有的属性。getConstructor(Class):
根据参数列表获取对应的public构造器对象。invoke():
执行对象方法。getDeclaredConstructor:
根据参数列表获取对应的构造器对象。setAccessible(true):
解除私有
反射原理
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象
。(包括基本数据类型)
注意: 每个类的实例都会记得自己是哪个Class实例生成的。
获取 Class有四种方式
- Class.forName
- 类名.class
- 对象.getClass
注解
Java 注解用于为 Java 代码提供元数据
。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。
元注解 :
可以理解为注解中的注解
- @Retention : 注解保留策略。分为:
RetentionPolicy.SOURCE
(只存源码),RetentionPolicy.CLASS
(会在class字节码文件中存在,但运行时无法获得),RetentionPolicy.RUNTIME
(注解会在class字节码文件中存在,在运行时可以通过反射获取到) - @Target: 注解作用范围
- @Document: 能够将注解中的元素包含到 Javadoc 中去
- @Inherited: @Inherited注解了的注解修饰了一个父类,其子类也会继承父类的注解。
- @Repeatable(JDK1.8加入): 可重复的。顾名思义说明被这个元注解修饰的注解可以同时作用一个对象多次,但是每次作用注解又可以代表不同的含义。
注解的属性
- 注解中是没有方法的,只有成员变量,变量名就是使用注解括号中对应的参数名,变量返回值注解括号中对应参数类型。
注解本质是个接口而接口成员变量是fianl修饰的没什么意义,就用方法当做属性。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface 注解 {
String name();
int age();
}
@注解(name = "小明", age = 21)
public class AnnotationTest
获取注解属性
必须使用元注解@Retention(RetentionPolicy.RUNTIME)
才能获取。
通过反射获取
public static void main(String[] args) {
Class<AnnotationTest> aClass = AnnotationTest.class;
//判断是否是指定注解
if (aClass.isAnnotationPresent(注解.class)) {
注解 annotation = aClass.getAnnotation(注解.class);
System.out.println(annotation.name());
System.out.println(annotation.age());
}