目录
- 1. &和&&的区别
- 2. goto是java保留字
- 3. finalize是属于Object类的一个方法,由GC调用
- 4. this和super不能同时出现在一个构造函数里面,因为this必然会调用其他构造函数,也就包含了super,这时候就有两个super,编译不会通过
- 5. 静态代码块和静态变量只会在加载类的时候执行唯一一次,所以能够优化程序性能
- 6. 静态执行顺序
- 7. 面向对象五大原则
- 8. 抽象类和接口的异同点
- 9. 内部类:成员内部类、局部内部类、匿名内部类、静态内部类
- 10. 值传递和引用传递:值传递是传递值的==拷贝==;引用传递是传递引用的==地址==
- 11. IO流(重点)
- 12. BIO/NIO/AIO的区别
- 13. Java获取反射的三种方法
1. &和&&的区别
&&:短路与,左边为false后不会对右边进行运算
2. goto是java保留字
3. finalize是属于Object类的一个方法,由GC调用
4. this和super不能同时出现在一个构造函数里面,因为this必然会调用其他构造函数,也就包含了super,这时候就有两个super,编译不会通过
5. 静态代码块和静态变量只会在加载类的时候执行唯一一次,所以能够优化程序性能
6. 静态执行顺序
- 执行父类静态代码块并对静态变量进行初始化(执行顺序与代码顺序有关)
- 执行子类的静态代码块并对静态变量进行初始化(执行顺序与代码顺序有关)
- 初始化父类实例变量
- 初始化父类构造函数
- 初始化子类治理变量
- 初始化子类构造函数
- 类中执行顺序优先级:静态代码块>main>普通代码块(即用{}括起来的代码块)>构造方法
- 类被初始化后会加载该类父类及其本身的静态部分,新建实例会加载该类父类机器本身的静态部分,然后加载非静态部分
类中存在静态变量时的执行顺序:父类静态代码块—父类静态变量—子类静态代码块—子类静态变量—父类普通代码块—父类构造方法—子类普通代码块—子类构造方法
总结:
总结引自https://twocups.cn/index.php/2020/01/22/16/
7. 面向对象五大原则
- 单一职责原则SRP:类功能单一,实现解耦,就像SQL的三大范式一样,一层一层的拆解,直至实现原子性
- 开放封闭原则OCP:开放拓展,封闭修改,就是说在做迭代的时候尽量不要修改原来的代码
- 里氏替换原则LSP:子代父业
- 依赖倒置原则DIP:高层次模块不应该依赖于低层次的模块,具体应依赖于抽象
- 接口分离原则ISP:功能分解,跟单一职责有点点类似
8. 抽象类和接口的异同点
相同点:
1. 接口和抽象类都不能实例化
2. 都位于集成的顶端,用于被其他类实现或继承
3. 都包含抽象方法,子类必须重写这些抽象方法
不同点:
1. 声明方式不同,一个是abstract一个是interface
2. 实现方式不同,一个是extends一个是implements
3. 抽象类可以拥有构造器
4. 抽象类中方法访问修饰符任意,接口默认public,不允许定义为private或者protected(定义了这接口还有啥用)
5. 多继承不同,接口可以多实现
6. 字段声明不同,接口字段默认static和final,抽象类任意
9. 内部类:成员内部类、局部内部类、匿名内部类、静态内部类
-
成员内部类(定义在类内部的成员位置上的非静态类)
public class Outer { private static int radius = 1; private int count =2; class Inner { public void visit() { System.out.println("visit outer static variable:" + radius); System.out.println("visit outer variable:" + count); } } } // 成员内部类可以访问外部类的所有变量和方法,包括静态和非静态,私有或共有 // 成员内部类的创建方式需要依赖外部类的实例 Outer outer = new Outer(); Outer.Inner inner = outer.new Inner(); inner.visit();
-
局部内部类(定义在方法中的内部类)
public class Outer { private int out_a = 1; private static int STATIC_b = 2; public void testFunctionClass(){ int inner_c =3; class Inner { private void fun(){ System.out.println(out_a); System.out.println(STATIC_b); System.out.println(inner_c); } } Inner inner = new Inner(); inner.fun(); } public static void testStaticFunctionClass(){ int d =3; class Inner { private void fun(){ // System.out.println(out_a); 编译错误,定义在静态方法中的局部类不可以访问外部类的实例变量 System.out.println(STATIC_b); System.out.println(d); } } Inner inner = new Inner(); inner.fun(); } } // 定义在实例方法中的局部类可以访问外部类的所有变量和方法,定义在静态方法中的局部类只能访问外部类的静态变量和方法 // 局部内部类的创建方式,在对应方法中,new public static void testStaticFunctionClass(){ class Inner { } Inner inner = new Inner(); }
-
匿名内部类(没有名字的内部类,必须继承或者实现一个已有的接口)
public class Outer { private void test(final int i) { new Service() { public void method() { for (int j = 0; j < i; j++) { System.out.println("匿名内部类" ); } } }.method(); } } //匿名内部类必须继承或实现一个已有的接口 interface Service{ void method(); } // 创建方式: new 类/接口{ //匿名内部类实现部分 }
匿名内部类特点:
- 匿名内部类必须继承一个抽象类或实现一个接口
- 匿名内部类不能定义任何静态成员和静态方法
- 当所在的方法的形参需要被匿名内部类使用时,必须声明为final
- 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法
-
静态内部类(定义在类内部的静态类)
public class Outer { private static int radius = 1; static class StaticInner { public void visit() { System.out.println("visit outer static variable:" + radius); } } } // 静态内部类可以访问外部类的所有静态变量,而不可访问外部类的非静态变量 // 静态内部类的创建方式:new 外部类.静态内部类() Outer.StaticInner inner = new Outer.StaticInner(); inner.visit();
内部类的优点:
- 内部类对象可以访问创建它的外部类对象的私有数据
- 内部类包外不可见,封装性好
- 内部类有效实现了java的“多继承”
- 匿名内部类可以很方便定义回调
内部类应用场景:
- 多算法场景
- 非面向对象的语句块
- 当某个类除了它的外部类,不再被其他类使用时
局部内部类和匿名内部类访问局部变量的时候变量必须加上final,因为生命周期不一致,局部变量直接存储在栈中,当方法执行结束后,非final的局部变量就被销毁。而局部内部类对局部变量的引用依然存在,如果局部内部类要调用局部变量时,就会出错。加了final,可以确保局部内部类使用的变量与外层的局部变量区分开,解决了这个问题。
10. 值传递和引用传递:值传递是传递值的拷贝;引用传递是传递引用的地址
11. IO流(重点)
划分:
* 按照流向划分:输入流和输出流
* 按照操作单元划分:字节流和字符流
* 按照流角色划分:节点流和处理流
Java IO流紧密联系,由下列四个抽象类基类派生而来
* InputStream/Reader:字节输入流/字符输入流
* OutputStream/Writer:字节输入流/字符输出流
12. BIO/NIO/AIO的区别
- BIO (Blocking I/O): 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。
- NIO (Non-blocking I/O): NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了NIO框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。NIO中的N可以理解为Non-blocking,不单纯是New。它支持面向缓冲的,基于通道的I/O操作方法。 NIO提供了与传统BIO模型中的
Socket
和ServerSocket
相对应的SocketChannel
和ServerSocketChannel
两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发 - AIO (Asynchronous I/O): AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的IO模型。异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO 是异步IO的缩写,虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。对于 NIO 来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO操作本身是同步的。查阅网上相关资料,我发现就目前来说 AIO 的应用还不是很广泛,Netty 之前也尝试使用过 AIO,不过又放弃了。
13. Java获取反射的三种方法
1. 通过New对象实现反射
2. 通过路径实现反射
3. 通过类名实现反射
```java
public class Get {
//获取反射机制三种方式
public static void main(String[] args) throws ClassNotFoundException {
//方式一(通过建立对象)
Student stu = new Student();
Class classobj1 = stu.getClass();
System.out.println(classobj1.getName());
//方式二(所在通过路径-相对路径)
Class classobj2 = Class.forName("fanshe.Student");
System.out.println(classobj2.getName());
//方式三(通过类名)
Class classobj3 = Student.class;
System.out.println(classobj3.getName());
}
}
```