1. 接口和抽象类的区别:
接口interface: Interface是为了把程序模块进行固化的契约,是为了降低偶合
成员变量 public static final ,接口中的所有方法都是抽象的 ,必须是用public修饰
抽象类abstract : 是为了把相同的东西提取出来,即重用,
没有构造器,抽象类是不能被实例化的,子类必须重写父类的所有抽象方法
含有抽象方法的类一定是抽象类,但是抽象类不一定含有抽象方法
一个类先继承在实现
2. Collection 集合
* List(存取有序,有索引,可以重复)
* ArrayList
* 底层是数组实现的,线程不安全,查找和修改快,增和删比较慢
* LinkedList
* 底层是链表实现的,线程不安全,增和删比较快,查找和修改比较慢
* Vector
* 底层是数组实现的,线程安全的,无论增删改查都慢
* 使用常识: 如果查找和修改多,用ArrayList, 如果增和删多,用LinkedList如果都多,用ArrayList
* Set(存取无序,无索引,不可以重复)
* HashSet
* 底层是哈希算法实现
* LinkedHashSet
* 底层是链表实现,但是也是可以保证元素唯一,和HashSet原理一样
* TreeSet
* 底层是二叉树算法实现
* 一般在开发的时候不需要对存储的元素排序,所以在开发的时候大多用HashSet,HashSet的效率比较高
* Map
* HashMap: 底层是哈希算法,针对键
* LinkedHashMap: 底层是链表,针对键
* TreeMap: 底层是二叉树算法,针对键
3.异常处理:
try:用来检测异常 catch:用来捕获异常的 finally:释放资源
Throwable的几个常见方法
a: getMessage()
获取异常信息,返回字符串。
b: toString()
获取异常类名和异常信息,返回字符串。
c: printStackTrace()
获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
throws和throw的区别
* a: throws
* 用在方法声明后面,跟的是异常类名
* 可以跟多个异常类名,用逗号隔开
* 表示抛出异常,由该方法的调用者来处理
* b: throw
* 用在方法体内,跟的是异常对象名
* 只能抛出一个异常对象名
* 表示抛出异常,由方法体内的语句处理
后续程序需要继续运行就try
后续程序不需要继续运行就throws
4.输入流和输出流:
Properties的load(new FileIputstream())和 store(new FileOutStream());第二参数是对列表参数的描述,可以给null
RandomAccessFile随机访问流,即能读又能写,还可在在指定位置写和读;
LineNumberReader是BufferedReader的子类, 具有相同的功能, 并且可以统计行号
InputStreamReader 是字节流通向字符流的桥梁
用默认编码表(gbk)读写,出现乱码,gbk一个汉字占两个字节,而utf-8一个汉字占3个字节打印流只操作数据目的
5.java中线程锁:
使用ReentrantLock类的newCondition()方法可以获取Condition对象
需要等待的时候使用Condition的await()方法, 唤醒的时候用signal()方法
不同的线程使用不同的Condition, 这样就能区分唤醒的时候找哪个线程了
ThreadGroup 线程组;
程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互。而使用线程池可以很好的提高性能,
尤其是当程 序中要创建大量生存期很短的线程时,更应该考虑使用线程池。线程池里的每一个线程代码结束后,
并不会死亡,而是再次回到线程池中成为空闲状态,等待下一个对象来使用。
在JDK5之前,我们必须手动实现自己的线程池, 从JDK5开始,Java内置支持线程池
线程池 : ExecutorService pool = Executors.newFixedThreadPool(2);
6.UDP和TCP区别:
UDP: 具有较好的实时性,工作效率比TCP高,适用于高速传输和实时性有较高的通信或者广播通信
传输数据不需要建立连接,是保证尽力交付数据,不保证可靠性
TCP: 需要进行三次握手,可靠性比较高
7.反射:
1. 反射:Class.forName("全类名"); constructor c -----c.newInstance(参数);
getDeclaredFields()获得全部属性,返回值Field; field.setAccessible(ture),
field.get(类的实例) getDeclaredMethod("方法名",参数); method.invoke(对象,参数)
2. 内省:基于反射 ,用来获得javaBean的属性和属性的get和set方法. 来模仿BeanUtils.populate()
8.动态代理:
1.得到代理对象:
第一个参数:类加载器器
ClassLoader loader = Demo.class.getClassLoader();
第二个参数:被增强类的接口数组: Person,SuperPerson是Man的接口:man.getInterfaces()
Class[] cs = {Person.class,SuperPerson.class};
第三个参数:InvocationHandler接口
2.可以使用匿名内部类的得到处理类对象
InvocationHandler hd = new InvcationHandler(){
public Object invoke(Object proxy,Method mthod,Object[] args){
}
};
3.可以同过实现处理接口的方式,得到处理类对象
public MyHandler implements InvocationHandler{
public Object invoke(Object proxy,Method mthod,Object[] args){
method.invoke(被增强类的对象,方法参数);
}
}
Objec objProxy = Proxy.newProxyInstance(loader,interfaces,invocationHandler);
4.明确处理类中invoke方法的三个参数分别表示什么:
第一个参数:Object proxy 表示代理对象
第二个参数: Method method 表示被增强类的方法对象
第三个参数:Object[] args 表示被增强类中的方法里面的参数
5.动态代理具体是怎么执行的:
Object proxy =----;//代理对象
Person p = (Person)proxy;// 代理对象
p.eat();
调用代理对象的方法,
1.第一步:步骤,去执行处理类中的invoke方法
2.第二步:步骤,在处理类中,调用了method.invoke方法,其实执行的被增强类中的方法。
动态代理的执行过程:
调用代理类对象的方法------>执行处理类中的invoke方法,在invoke方法里面,执行method对象方法
---->被增强类中的方法
9: 注解
1. 注解和注释的区别: 注释:给程序员看的. 注解:给虚拟机看的(让虚拟机看到程序中的注解,注解代表程序的一些特殊功能)
2.JDK中提供了三个注解:
①@override :描述子类重写父类的方法; (JDK6.0版本上,可以应用在实现上)
②@suppresswarnings("all") : 压制所有警告.属性名就是value;
③.@Deprecated : 描述方法过时.
3.自定义注解 :
@Retention 指定注解的保留策略
@Target 指定注解的作用位置,
@Documentd
public @interface 注解名{
注解的属性:int a() default 2;
}
日期类型对于注解无效,只有基本数据类型字符串类型,class类型,注解类型,枚举类型,以上类型的一维数组可以.
如果注解中只有一个value属性名(string value()),可以省略value,直接写值.
默认的自定义的注解存在于源代码阶段,需要延长注解的存在时间,使用元注解:修饰其他注解 @Retention(Runtime);
4.自定义注解结合反射.
1.定义一个核心的运行类,建立main方法,利用反射获得测试类的class,获得所有方法,
2.遍历每个方法,查看每 个方法有注解,(method.isAnnotationparesent()有注解的执行.
10.监听器:
1.监听器listener 的概述: 就是一个java类,用来监听其他的java的状态的变化 作用: 主要应用在图形化的界面比较多,GUI, Android,
2.监听器的术语:
事件源:指的是被监听的对象(汽车)
监听器: 指的是监听对象(报警器)
事件源与被监听器的绑定: 就是在汽车上安装报警器
事件: 指的是事件源的改变(汽车报警器从不响到响)
3.图形化小窗口: 一个java类 继承JFrame, new 自定义本类,
1. 设置窗口大小serbounds(); 设置窗口显示,
2.设置监听器addwindowlistener(new 自定义类);
3.建立一个2.类 实现 windowlistener接口,重写windowclosing()关闭窗口
11. JDK新版本特性:
JDK8: jdk默认在非静态方法的参数上引用当前对象实例
1. lambda : 匿名函数 只需要知道输入和输出,不需要知道名称 参数 -> 实现逻辑 放回一个实例:
接口 test1 = (参数列表) -> {实现逻辑};限制: 接口内只能有一个方法
2. LocalDate 线程安全的,而且月份从1开始,方法更加好用
3. 使用Optional容器可以快速的定位NPE,并且在一定程度上可以减少对参数非空检验的代码量
4. 接口内的默认方法 : 加default,可以直接写具体实现 , 子接口继承后,可以重写默认方法
5. function 支持链式编程 UnaryOperator: 一元函数类型 传入值和返回值一样类型 BiFunction 传入两个参数
6. 方法的引用: 非静态方法 Function<Integer,Integer> function = 实例名称::eat;
静态方法 Function<Integer,Integer> function = 类名称::eat;
构造方法 Supplier<Dog> supplier = Dog::new; 带参数为: Function<Integer,Integer> function
7.变量的引用: 可以在lambda表达式中的逻辑里面加入方法或类的变量
8. 级联表达式: Function<Integer, Function<Integer,Integer>> fun = x -> y -> x+y;
柯里化: 把多个参数的函数转化为只有一个参数的函数 fun.apply(3).apply(2);
高阶函数: 函数里面泛型还是函数
9. IntStream.of(数组).sum() 数组求和
10.Stream流 : Stream 流: 底层是Fork-Join原理,不要轻易用
map 将一种类型的值转换为另外一种类型的值。
flatMap 将多个Stream连接成一个Stream,这时候不是用新值取代Stream的值,与map有所区别,
这是重新生成一个Stream对象取而代之。
取出A集合里面元素中另外元素的集合 : 比如: A集合里面是string类型, 取出里面字符串的每个字符char类型
peek方法用于debug, 用于展示执行到Stream链式编程中间哪里出问题了
limit 使用, 主要用于无限制流
11. 短路操作指的是找到符合条件的元素就结束本次迭代,非短路操作则是需要完全迭代结束才行。
非短路操作:
1. 并行流 ,并行输出,顺序乱掉的
str.chars().parallel().forEachOrdered/forEach
2.收集流 ,收集成集合
collect/toArray Stream.of(str.split(" ")).collect(Collectors.toList())
3.对字符串操作 ,比如: 字符串中间加 | 等等
Stream.of(str.split(" ")).reduce((s1, s2) -> s1+"|"+s2);
4. 求最大值,最小值
min/max/count
短路操作:
findFirst/findAny
allMatch/anyMatch/noneMatch
12 并行流 parallel() 默认使用: ForkJoinPool线程池 ,线程数当前的CPU,可以改
可以更改为自己的线程池 IntStream.range(1, 100).parallel()
串行流:顺序的输出单线程 sequential()
收集器: 汇总/分块/分组(根据班级分组后求学生人数)
收集数组 list.stream().map(i -> i.length()).collect(Collectors.toList());
13 . reactive Stream : 前提条件请求一定要大于256
背压: 发布者/订阅者 发布者发布消息, 订阅者订阅消息, 当订阅者可以告诉发布者要减少接收消息
还是增加接收消息
1 . 发布者 SubmissionPublisher<发送类型> publiser = new SubmissionPublisher<Integer>();
2. 处理器: 进行参数校验等: class MyProcessor
extends SubmissionPublisher<String>implements Processor<Integer, String>
3. 发布者订阅处理 器 publiser.subscribe(processor);
4. 定义最终订阅者, 消费处理过的数据 Subscriber<String> subscriber = new Subscriber<String>() {
5. 处理器和最终订阅者建立关系
14 web-flux :
http: 都是一问一答 而他不同
15 Reactor : Reactor模式是事件驱动模型,有一个或多个并发输入源,有一个Service Handler,
有多个Request Handlers;这个Service Handler会同步的将输入的请求(Event)多路复用的分发给
相应的Request Handler。从结构上,这有点类似生产者消费者模式,即有一个或多个生产者将事件
放入一个Queue中,而一个或多个消费者主动的从这个Queue中Poll事件来处理;而Reactor模式则
并没有Queue来做缓冲,每当一个Event输入到Service Handler之后,该Service Handler会主动的
根据不同的Event类型将其分发给对应的Request Handler来处理
优点
1)响应快,不必为单个同步时间所阻塞,虽然Reactor本身依然是同步的;
2)编程相对简单,可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销;
3)可扩展性,可以方便的通过增加Reactor实例个数来充分利用CPU资源;
4)可复用性,reactor框架本身与具体事件处理逻辑无关,具有很高的复用性;
缺点
1)相比传统的简单模型,Reactor增加了一定的复杂性,因而有一定的门槛,并且不易于调试。
2)Reactor模式需要底层的Synchronous Event Demultiplexer支持,比如Java中的Selector支持,操作系统
的select系统调用支持,如果要自己实现Synchronous Event Demultiplexer可能不会有那么高效。
3) Reactor模式在IO读写数据时还是在同一个线程中实现的,即使使用多个Reactor机制的情况下,那些共享
一个Reactor的Channel如果出现一个长时间的数据读写,会影响这个Reactor中其他Channel的相应时间,
比如在大文件传输时,IO操作就会影响其他Client的相应时间,因而对这种操作,
使用传统的Thread-Per-Connection或许是一个更好的选择,或则此时使用Proactor模式。
16 元数据:
元数据是指用来描述数据的数据,更通俗一点,就是描述代码间关系,或者代码与其他资源(例如数据库表)之间内在联系的数据,在编程语言上下文中,元数据是添加到程序元素如方法、字段、类和包上的额外信息。对数据进行说明描述的数据
java就是通过注解来表示元数据的