一条咸鱼的java学习笔记第6天

文章目录

1.什么是泛型?泛型的好处?泛型和方法重载有什么联系?泛型可以使用基本类型么(泛型要求包含的是对象类型)?

泛型其实就是在定义类、接口、方法的时候不局限地指定某一种特定类型,而让类、接口、方法的调用者来决定具体使用哪一种类型的参数。
泛型好处:
1.泛型简单易用
2.类型安全 泛型的主要目标是实现java的类型安全。 泛型可以使编译器知道一个对象的限定类型是什么,这样编译器就可以在一个高的程度上验证这个类型
3.消除了强制类型转换 使得代码可读性好,减少了很多出错的机会
4.Java语言引入泛型的好处是安全简单。泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
在这里插入图片描述

2.常用的集合类有哪些?具有哪些特性?是否有序?是否可以为null?是否排序?是否重复? 每个集合类底层的数据存储结构?

在这里插入图片描述
集合和泛型
集合:
java将一组数据作为一个管理单元进行管理;集合中存储的都是对象类型;8种基本类型转换为8种包装类类型进行存储;
集合分为两大类:
collection接口:set接口、List接口
Map接口:

List:
List集合是一组有序的集合元素,List有下标,可以通过下标访问集合的元素(get方法),
List集合遍历:
标准for循环
增强型的for循环遍历
Iterator迭代器遍历

ArrayList:线性表数组实现。数组读写快,增删慢。
LinkList:线性表(双向链表)读写慢,增删快
Vector:线性表(数组)。是List接口实现子类中的线程安全类。
链表实现和数组实现的异同点(ArrayList和LinkedList的异同点)
ArrayList底层是数组实现的,特点读写快,增删慢。数组连续存储,有下标。集合读写操作频繁时可以使用ArrayList。
LinkedList底层是链表实现的,遍历时需要每次从头到尾一次遍历,所有读写慢,增删快。当集合增删频繁时,可以使用LinkedList。

采用Hash存储的集合都是无序的;
采用链表存储的集合都是有序的;
采用二叉树型结构存储的集合都是排序的;
带有排序规则的集合元素不能为null;
没有排序功能的集合可以为null;

Set接口
set集合是采用hash散列算法进行存储的集合;因为set集合采用hash散列存储,所有没有下标
【原因:散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值】
总结:集合中凡是采用hash散列存储的集合都没有下标,不能通过下标来进行读取元素的值;

Set集合遍历:foreach遍历、Iterator迭代器遍历(没有下标所以不能用for循环遍历)
HashSet:线性表(hash表)
LinkedHashSet:线性表(hash表,双向链表)
TreeSet:树形结构。平衡二叉树

Map接口
Map集合的元素是一个键值对,以键作为存储的标识,进行散列存储;键和值的类型都是对象类型。java中用Entry抽象封装了键值对,map集合中存储的是一个个的键值对,也就是map中存储的是Entry对象,map可以通过get(key)的方法来获得key的值。

Map集合的遍历:
map集合没有迭代器,都是可以获取所有键集合的迭代器,可以获取所有entry集合的迭代器,先取出Key的Set集合或者Entry的Set集合,value的集合,然后对其进行遍历。
HashMap:线性表(hash表
LinkedHashMap:
TreeMap:

是否有序?是否重复?是否可以为null值?是否排序?
有序:存入集合时元素的顺序和取出集合元素时的顺序一致
排序:取出时元素按照自然顺序进行排序

工具类:
Collection、ArrayList工具类、Comparator和Comparable接口
泛型:集合中指定具体的子类类型,可以避免强制类型转换(向下溯型)
在这里插入图片描述

3.Comparator和Comparable接口的作用和异同点?

用于比较的接口,使对象之间有能比较的能力。

相同:
Comparator和Comparable都是java的一个接口,并且是用来对自定义的class比较大小的。
都是用于Set、TreeSet等比较,都可以用于对对象类型的比较。
不同:
comparator是比较器,可以直接执行。接口中的compare方法有两个参数,能对基本数据类型做比较,也能对类对象里的元素做比较。
comparable通过比较实体对象来调用。但是一个实体只能实现一个接口,所以扩展性不是很好。comparaTo方法有一个参数,用于对类对象里的元素进行比较。

public interface Comparable<T>{
public int comparaTo(T o);
}
x.compareTo(y);//比较x和y的大小,若返回负数,则x<y;若返回正数,则x>y;若返回0,则相等


public interface Comparator<T>{
int compare(T o1 , T o2);
boolean equals(Object object);
}
int compare(T o1 , T o2);//比较o1和o2的大小,返回负数,则o1<o2;返回正数,o1>o2;返回0,则o1==o2

4.HashMap的底层实现的数据结构?1.7- 数组+链表;1.8+ 数组+链表+红黑树

从上图我们可以看出HashMap底层实现还是数组,只是数组的每一项都是一条链。
从上图我们可以看出HashMap底层实现还是数组,只是数组的每一项都是一条链。
Hash算法可以将一个数据转换为一个标志,这个标志和源数据的每一个字节都有十分紧密的关系。

散列一般指Hash(散列函数)
Hash,一般翻译做散列、杂凑,或音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值

7.什么是红黑树? 在HashMap中链表是如何转换为红黑树的? 为什么使用红黑树?

红黑树其实就是一种自平衡的二叉查找树。他这个自平衡的特性就是对HashMap中链表可能会很长做出的优化。

红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:

性质1. 节点是红色或黑色。

性质2. 根节点是黑色。

性质3 每个叶节点(NIL节点,空节点)是黑色的。

性质4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)

性质5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

下面这棵树就是一个典型的红黑树

在这里插入图片描述
在这里插入图片描述

8.HashMap的负载因子是(0.75);HashMap的初始长度是多少(16)?HashMap是如何扩容的?(按照16的整数倍进行扩容。)

Map<String,Object> map = new HashMap<>(30);内存中初始化的map长度为多少?32
负载因子 loadFactor表示一个散列表的空间的使用程度,有这样一个公式:initailCapacity*loadFactor=HashMap的容量。
所以负载因子越大则散列表的装填程度越高,也就是能容纳更多的元素,元素多了,链表大了,所以此时索引效率就会降低。
反之,负载因子越小则链表中的数据量就越稀疏,此时会对空间造成烂费,但是此时索引效率高。

9.什么是对象流?是将内存中的某个时间节点的状体信息以字节流的形式持久化到硬盘文件中

10.什么是序列化?什么是反序列化? Serarizable接口的作用?

序列化 (Serialization)是将对象的状态信息转换为二进制的过程
实现序列化需要实现java.io.Serializable接口。
反序列化:就是通过序列化后的字段还原成这个对象本身。
 Serializable接口是启用其序列化功能的接口。实现java.io.Serializable 接口的类是可序列化的。没有实现此接口的类将不能使它们的任意状态被序列化或逆序列化。。

11.Transient关键字作用?是否可以和final、static搭配使用?以及他们之间的区别?

首先介绍一下序列化Serializable

通常一个类实现序列化方式是实现序列化接口: class XXX implements Serializable

序列化的作用:把数据长久的保存在磁盘中,磁盘和内存是不同的,内存一般在程序运行时占用,数据保存周期短,随程序结束而结束,磁盘可以长久保存数据

transient关键字的作用,在已实现序列化的类中,有的变量不需要保存在磁盘中,就要transient关键字修饰,如银行卡密码等,就这个作用------在已序列化的类中使变量不序列化
tansient只能修饰变量不可以修饰方法和类
被static修饰的变量 不会被序列化

12.什么是进程?什么是线程?进程和线程之间的异同点?

进程: 具有独立功能程序在某个数据集合上的一次执行过程。

线程: 进程内的一个执行实体或执行单元。

进程和线程的区别:

(a) 不同进程的地址空间是独立的,而同一进程内的线程共享同一地址空间。一个进程的线程在另一个进程内是不可见的。

(b) 在引入线程的操作系统中,进程是资源分配和调度的单位,线程是处理机调度和分配的单位,资源是分配给进程的,线程只拥有很少资源,因而切换代价比进程切换低。

13.线程的状态以及转换方式?进程三态、五态的状态转换图?

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

14.java多线程编程的实现方式?常用的线程操作的方法?

1.使用Thread类方式
继承Thread类 重写run方法
Run方法中就是线程需要执行的任务或者执行的代码
如何调用线程 声明 A a = new A();
启动线程 不是调用run方法 而是调用start方法 a.start();
使用开启多线程后 代码不会从上往下进行执行
2.使用实现runnable接口方式

3.使用匿名内部类方式
4. Callable
5.使用线程池创建线程

常用的线程操作的方法:
线程休眠方法:sleep()
线程让步:yield()
等待其他线程终止:join()方法
线程停止的三种方法:
设置标记位停止线程,可以使线程正常退出
调用stop方法强制停止线程
调用Thread类的interrupt()方法

15.多线程中可以直接调用run方法,执行线程么

run()相当于线程的任务处理逻辑的入口方法,它由Java虚拟机在运行相应线程时直接调用,而不是由应用代码进行调用。

而start()的作用是启动相应的线程。启动一个线程实际是请求Java虚拟机运行相应的线程,而这个线程何时能够运行是由线程调度器决定的。start()调用结束并不表示相应线程已经开始运行,这个线程可能稍后运行,也可能永远也不会运行。
首先Thread类中run()和start()方法的区别如下:
run()方法:在本线程内调用该Runnable对象的run()方法,可以重复多次调用;
start()方法:启动一个线程,调用该Runnable对象的run()方法,不能多次启动一个线程;
run方法可以创建一个线程,但是相当于同步的方式,没有多线程的存在。
只有调用start方法才是交给jvm管理,才是多线程。

run方法不能启动线程,只有start方法才能真正启动线程。
调用start()方法后,线程会被放到等待队列,等待CPU调度,并不一定要马上开始执行,只是将这个线程置于可运行状态。通过调用jvm,线程Thread会调用run()方法,执行本线程的线程体。

16.线程类实现之后,调用run方法和start方法有什么区别?

线程对象调用run方法不开启线程。仅是对象调用方法。线程对象调用start开启线程,并让jvm调用run方法在开启的线程中执行。

17.线程死锁?产生死锁的四个必要条件?

由于两个或多个线程相互持有对方所需要的资源,导致这些线程处于等待状态,无法前往执行。
当线程进入对象的Synchronize代码块时,便占有了资源,直到他退出该代码块或者调用wait方法,才释放资源,在此期间,其他线程将不能进入该代码块。当线程互相持有对方所需的资源时,会互相等待对方释放资源,如果线程都不主动释放所占资源,将产生死锁。

(1)互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源

(2)请求和保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放

(3)不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释放

(4)环路等待条件:是指进程发生死锁后,必然存在一个进程–资源之间的环形链

18.如何避免线程产生死锁?Synchronize关键字的用法?

三种用于避免死锁的技术:
1.加锁顺序(线程按照一定的顺序加锁)
2.加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)
3. 死锁检测

Synchronize关键字的用法:
synchronize关键字被加锁对象必须是对象类型(基本类型使用包装类类型替代)
synchronize加锁对象是引起多线程死锁的关键资源对象。
使用synchronize关键字进行同步时,主要考虑被加锁的对象,以及被加锁对象的粒度大小,被加锁对象的粒度越小越好,因为同步处理是需要系统开销的。
用法:
可以修饰方法,作为同步方法使用
可以修饰语句块,对该语句块进行同步处理。

synchronize(被加锁对象){ 
同步块语句
}

19.线程同步?

当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作

20.线程的通信机制(wait-notify机制)

java实现线程通信机制主要通过以下几种方式

1 while()轮询

2 等待/通知机制

wait()、notify()、notifyAll()结合synchronized关键字

3 条件对象:Condition

Condition和ReentrantLock重入锁

等待/通知机制

synchronized是JVM提供的内置锁,我们通过java中的生产者消费者模式来看看wait/notify是如何实现线程间通信的

wait()/notify()/notifyAll()是Object类定义的方法,必须与synchronized一起使用,更确切的来说是在synchronized临界区内使用,

也就是说调用wait()方法的前提是该线程已经获取锁,调用notify()/notifyAll()的前提是也是该线程已经获取了锁,

wait() : 使当前线程进入阻塞状态,退出临界区,释放CPU,暂时放弃所获取的锁,当其他线程调用notify()/notidyAll()方法的时候,会唤醒一个或者多个处于等待该线程可能会被唤醒然后重新取竞争获取锁,如果重新获得了锁,被唤醒的线程会继续从上次阻塞的地方执行。

notify()/notifyAll():当前线程调用此方法,会唤醒之前阻塞的线程,但是notify()/notifyAll()方法不会释放锁,而是会继续往下执行,直到遇到wait()方法才会释放锁,所以一般线程调用完成notify()/notifyAll()方法后,都会调用wait()释放锁,退出临界区,从而让其他线程有机会获取锁

21.ConcurrentHashMap如何实现多线程并发的? CAS无锁化解决多线程并发;【乐观锁】;Synchronize关键字解决多线程并发【悲观锁】

22.什么是乐观锁?什么是悲观锁?

悲观锁是一个事务锁定了一些数据之后,只有当当前锁提交了事务,释放了锁,其他事务才能获得锁并执行操作。

乐观锁是首先假设数据冲突很少,只有在数据提交修改的时候才进行校验,如果冲突了则不会进行更新。

23.OIS7层模型和Tcp/Ip4层模型?

在这里插入图片描述

24.OSI7层模型中各层模型的主要协议、运行的设备、端口号有哪些?

在这里插入图片描述

25.常用的网络通信协议:TCP、UDP、Http、ftp、pop3、smtp

26.TCP和UDP的区别?以及网络编程实现方式

TCP协议:
TCP面向连接是可靠的,TCP三次握手建立连接,四次握手释放连接。
TCP网络编程:
使用Socket作为客户端与服务器端ServerSocket通过IP地址+端口号的方式建立连接,使用输出输入流进行信息交互,如果要传输对象流则需要满足序列化的要求。TCP编程是先建立连接通道,然后再传输信息的

UDP协议:
UDP是非面向连接的不可靠的,UDP传输效率比TCP高,但是可靠性比TCP低。

UDP网络编程
客户端和服务器端都是使用DatagramSocket进行信息的发送和接收。发送和接收的信息是存放在DatagramPacket中,数据包中存放了连接服务器的IP地址和端口号。UDP是将传输信息放在数据包中,直接发送到网络上,不需要建立连接通道。

TCP与UDP区别:
TCP面向连接,UDP是无连接的,即发送数据之前不需要建立连接
TCP提供可靠的服务,通过TCP连接传送的数据,无差错、不丢失。不重复、且按序列到达。UDP尽最大努力交付,即不保证可靠交付。
TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流,UDP是面向报文的。UDP没有拥塞阻塞控制,因此网络出现拥塞不会使源主机的发送速率降低。
每一条TCP连接只能是点到点的,UDP支持一对一、一对多、多对一和多对多的交互通信。
TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道。

ps:报文(message)是网络中交换与传输的数据单元,即站点一次性要发送的数据块。报文包含了将要发送的完整的数据信息,其长短很不一致,长度不限且可变。

27.如何获取一个类的描述类Class类的实例对象?(至少有3中方式)

1.通过class的方式创建Class实例:类名.class

2.通过对象的getClass()方法获得。

3.通过Class类的forName()方法来获得。

28.什么是反射(从解剖学的视角来观察动态操作类构成的一种思想)?反射的作用和意义?什么是Class类,作用是什么?

反射主要是指程序可以访问、检测和修改其本身状态或行为的一种能力。
java反射机制是在运行状态中,对于任意一个实体类,都能够获取这个类的所有属性和方法,对于任意一个对象,都能够调用他的任意方法和属性。这种动态获取类的构造信息以及动态调用实例对象的行为方法的功能成为java语言的反射机制。

反射的作用:
通过反射可以使程序代码访问装载到jvm中的类的内部信息
获取已装载类的成员变量信息
获取已装载类的方法
获取已装载类的构造方法信息

class类:
class类是一个抽象封装类。
jvm在反射机制中将一个类的构成信息进行抽象封装,使用class类来进行描述;
class是对某一个类的抽象封装,class是来自于一个具体的类在jvm执行时所获取信息的抽象封装。
class没有公共构造方法,class对象是在加载类时由java虚拟机以及通过调研类加载器中的defineclass方法自动构造的。

在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类,编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息。

29.使用java在内存中创建一个新对象的方式有哪几种?

new创建;
对象流创建;
反射创建;
克隆创建;

new创建: A a = new A();
对象流创建:

ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Person p5 = (Person) in.readObject();

反射创建: 调用java.lang.Class或者java.lang.reflect.Constuctor类的newInstance()实例方法。

Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee").newInstance();
//或者
Employee emp2 = Employee.class.newInstance();
//或者
Constructor<Employee> constructor = Employee.class.getConstructor();
Employee emp3 = constructor.newInstance();

克隆创建:使用以上三种方式的一种

Employee emp4 = (Employee) emp3.clone();

30.什么是注解?注解和注释的区别?

注释:是对程序的解释说明,是给用户看的,注释不参与程序的编译执行。
注解:是对程序的补充说明,是给jvm看的,注解是参与程序的编译运行的。

31.常用的元注解有哪些?各有什么作用?

@Target
表示该注解可以用于什么地方,可能的ElementType参数有:
CONSTRUCTOR:构造器的声明
FIELD:域声明(包括enum实例)
LOCAL_VARIABLE:局部变量声明
METHOD:方法声明
PACKAGE:包声明
PARAMETER:参数声明
TYPE:类、接口(包括注解类型)或enum声明

@Retention
表示需要在什么级别保存该注解信息。可选的RetentionPolicy参数包括:
SOURCE:注解将被编译器丢弃
CLASS:注解在class文件中可用,但会被VM丢弃
RUNTIME:VM将在运行期间保留注解,因此可以通过反射机制读取注解的信息

@Document
将注解包含在Javadoc中

@Inherited
允许子类继承父类中的注解

32.常用的排序算法以及稳定性?对应的时间复杂度和空间复杂度分析?

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值