**每日更新java知识库**

如需转载分享,请标明出处,且不用于盈利为目的,谢谢合作!

每日更新java知识库

一、java基础

HashMap、LinkedHashMap、ConcurrentHashMap、ArrayList、LinkedList的底层实现
1.HashMap:底层是一个数组+链表实现
2.LinkedHashMap:底层是Hash表和链表的实现
3.ConcurrentHashMap:基于双数组和链表的Map接口的同步实现
4.ArrayList:底层都是采用数组方式来实现的
5.LinkedList:底层是由双向循环链表实现的

HashMap和Hashtable的区别
1.hashMap继承AbstractMap,hashtable继承Dictionary,两个都实现Map接口
2.hashMap中的方法不是同步的、线程不安全,hashtable中的方法是同步的、线程安全;hashMap同步的问题可以通过Collections的一个静态方法解决:Map Collections.synchronizedMap(Map map)
3.hashMap中,null可以作为键(只能有一个null)和值(一个或多个null),hashMap中判断是否存在某个键用containskey()方法。
Collection和Collections的区别
1.Collection是个接口,Set接口和List接口都继承Collection
2.Collections是个工具类,提供有关集合操作的静态方法
ArrayList、LinkedList和Vector的区别
1.ArrayList、LinkedList线程不安全、不同步,Vector线程安全、同步
2.ArrayList和Vector底层以数组的方式存储,LinkedList底层以链表的方式存储
3.LinkedList适合插入元素和删除元素,ArrayList和Vector适合查询元素
4.ArrayList在元素填满容器时会自动扩充容器大小为原来的一半,而Vector则是原来的一倍,因此ArrayList更节省空间
JDK 和 JRE 有什么区别
1.jdk:java开发工具包,提供java开发环境和运行环境;jdk包含了jre,同时包含了编译java源码的javac,还有很多java程序调试和分析工具
2.jre:为java运行提供环境
3.编写程序需要jdk,运行程序需要jre
equals()和 == 的区别是什么
1.==比较的是地址,equals()比较的是值
2.==比较的引用是否相同,equals()比较的值是否相同
3.==判断两个变量或实例是否指向同一内存地址,equals()判断两个变量或实例的内存地址的值是否相同
两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?
1.两个对象hashCode()值相同,equals()不一定相同(hashCode存在散列值冲突,概率小)
2.两个对象equals()值相同,hashCode()一定相同
final的作用
1.final可以修饰变量、方法、类
2.修饰变量,变量不能够被更改;修饰方法,方法不能够被重写;修饰类,类不能够被继承
java 中的 Math.round(-1.5) 等于多少
1.Math.floor(11.3):11;Math.floor(-11.3):-12 向下
2.Math.ceil(11.3):12;Math.ceil(-11.3):-11 向上
3.Math.round(x)相当于Math.floor(x+0.5) 四舍五入
java的八种基本数据类型
1.byte、short、int、long、char、float、double、boolean
String 类的常用方法都有那些
1.equals()
2.isEmpty()
3.compareTo()
4.subString()
5.indexOf()
6.charAt()
7.length()
8.concat()
9.endwith()
10.contains()
普通类和抽象类有哪些区别
1.抽象类里的方法必须都是抽象方法;有抽象方法,类一定是抽象类
2.抽象类被继承,那么子类必须实现所有抽象方法,否则这个子类必须为抽象类
3.抽象类不能够实例化
4.抽象类中可以有构造方法,抽象的方法不能够声明为静态,子类必须继承父类的一个构造方法
5.抽象方法只需声明,无需实现,抽象方法中允许有普通方法作为主体
抽象类能用final修饰吗
final修饰符不能用来修饰接口和抽象类
接口和抽象类有什么区别
1.接口和抽象类不能实例化,如实例化,接口变量指向实现接口所有方法的类对象,抽象类变量指向实现所有抽象方法的子类对象
2.抽象类被子类继承,接口被类实现
3.接口只能做方法声明,抽象类可以坐方法声明,也可以做方法实现
4.接口定义的变量只能是公共的常量,抽象类中的变量为普通变量
5.接口中的方法必须全部实现,否则该类也是接口;抽象类中的方法必须全部被子类实现,否则该类也是抽象类
6.接口是设计结果,抽象类是重构结果
7.抽象类可以没有抽象方法
8.如果一个类中有抽象方法,那么该类一定是抽象类
9.抽象类中的方法要被实现,所以不能是静态的,也不能是私有的
10.接口可以继承接口,也可以多继承;但类只能单根继承
java的容器都有哪些
1.List 有序,可重复
2.Set 无序,不可重复
3.Map 无序, key值不可重复,value值可重复
4.数组
5.java.util下的集合容器
List与数组之间转换
1.List转换成为数组:调用ArrayList的toArray方法
2.数组转换成为List:调用Arrays的asList方法
Queue接口中的poll()和remove()区别
remove方法和poll方法都是删除队列的头元素,remove方法在队列为空的情况下将抛异常NoSuchElementException,而poll方法将返回null
java中哪些集合类是线程安全的?
1.Vector:就比Arraylist多了个同步化机制(线程安全)。
2.Hashtable:就比Hashmap多了个线程安全。
3.ConcurrentHashMap:是一种高效但是线程安全的集合。
4.Stack:栈,也是线程安全的,继承于Vector。
怎么确保一个集合不能被修改
1.List Collections.unmodifiableList(List)
2.Set Collections.unmodifiableSet(Set)
3.Map Collections.unmodifiableMap(Map)
假设添加了一个对象到集合,使用Collections下的unmodifiableXX()方法,会报java.lang.UnsupportedOperationException错,意思就是不能够修改集合
Iterator和ListIterator有什么区别
1.Iterator在Set和LIst中都有定义,但ListIterator仅在List中有或实现类
2.ListIterator有add()方法,可以向集合添加对象,而Iterator不可以
3.ListIterator和Iterator都有hasNext()和next()方法顺序向后遍历,但ListIterator有hasPerivous()和pervious()方法逆序向前遍历,Iterator不可以
4.ListIterator可以定位当前索引的位置,nextIndex(),previousIndex(),而iterator不可以
5.都可以删除对象用remove()方法,但ListIterator可以实现对象的修改用set()方法,iterator不可以
并行和并发的区别
1.并发:指应用能够交替执行不同的任务
2.并行:指应用能够同时执行不同的任务
线程和进程的区别
1.一个进程至少有一个线程,而线程不是
2.线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制
3.线程的划分尺度小于进程,使得多线程程序的并发性高
java中的线程分为几种
1.守护线程:如垃圾回收线程;专门用于服务其他的线程的服务线程,如果用户线程还没执行完,jvm就不会退出,守护线程就不会停止,这是为了执行垃圾回收任务
2.用户线程:如应用自定义线程;应用程序里的线程,一般都是用户自定义线程,用户自己创建的线程
创建线程的方式
1.继承Thread类

//(1)继承Thread类
public class ThreadExt extends Thread {
	//(2)重写run()方法,线程的执行主体
	@Override
	public void run() {
		System.out.println("Thread is running...");
	}
	public static void main(String[] args){
		//(3)创建Thread子类对象,即为线程对象
		ThreadExt threadExt = new ThreadExt();
		threadExt.start();
	}
}

2.实现Runnable接口

//(1)实现runnable接口
public class RunnableImpl implements Runnable {
	//(2)重写run()方法,线程执行主体
	@Override
	public void run() {
		System.out.println("Thread is running...");
	}
	public static void main(String[] args){
		RunnableImpl runnable = new RunnableImpl();
		//(3)runnable对象作为Target
		Thread thread = new Thread(runnable);
		thread.start();
	}
}

3.使用Callable接口和FutureTask类创建

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

//(1)创建Callable接口的实现类CallableImpl
public class CallableImpl implements Callable<Integer> {
	//(2)重写call()方法作为线程的执行主体,并设置返回值
	@Override
	public Integer call() throws Exception {
		System.out.println("Thread is running...");
		Thread.sleep(1000);
		return 1;
	}
	public static void main(String[] args) throws ExecutionException, InterruptedException {
		//(3)创建Callable的实现类
		CallableImpl callable = new CallableImpl();
		//(4)创建FutureTask类对象
		FutureTask<Integer> futureTask = new FutureTask<>(callable);
		//(5)把FutureTask实现类对象作为target,通过Thread类对象启动线程
		Thread thread = new Thread(futureTask);
		//(6)启动线程start()方法
		thread.start();
		System.out.println("do something else...");
		//(7)通过get方法获取返回值
		Integer integer = futureTask.get();
		System.out.println("The thread running result is :" + integer);
	}
}

interrupt()的作用
中断本线程,本线程中断自己是被允许的;其它线程调用本线程的interrupt()方法时,会通过checkAccess()检查权限。这有可能抛出SecurityException异常。
如果本线程是处于运行状态:调用线程的wait(), wait(long)或wait(long, int)会让它进入等待(阻塞)状态,或者调用线程的join(), join(long), join(long, int), sleep(long), sleep(long, int)也会让它进入阻塞状态。若线程在阻塞状态时,调用了它的interrupt()方法,那么它的“中断状态”会被清除并且会收到一个InterruptedException异常。例如,线程通过wait()进入阻塞状态,此时通过interrupt()中断该线程;调用interrupt()会立即将线程的中断标记设为“true”,但是由于线程处于阻塞状态,所以该“中断标记”会立即被清除为“false”,同时,会产生一个InterruptedException的异常。
如果线程被阻塞在一个Selector选择器中,那么通过interrupt()中断它时;线程的中断标记会被设置为true,并且它会立即从选择操作中返回。
如果不属于前面所说的情况,那么通过interrupt()中断线程时,它的中断标记会被设置为“true”。
中断一个“已终止的线程”不会产生任何操作。
runnable 和 callable 有什么区别
1.都是接口,都采用new Thread().start()启动线程
2.runnable没有返回值,callable有返回值,是个泛型,需要调用FutureTask.get()得到,此方法会阻塞主进程的继续往下执行,如果不调用不会阻塞
3.Callable接口的call()方法允许抛出异常;Runnable的run()方法异常只能在内部消化,不能往上继续抛
线程有哪些状态

新建状态 就绪状态 运行状态 阻塞状态 死亡状态 线程对象调用start()方法启动线程 获得cpu资源,执行run()方法 被其他线程抢到了cpu资源 sleep()方法时间到,执行notify()、notifyAll() ①线程调用sleep()、wait()方法 ②线程调用一个在I/O上被阻塞的操作 ③线程试图得到一个正在被其他线程持有的锁 ④线程正在等待某个触发条件 ①run()方法执行完而自然死亡 ②一个未捕获的异常终止了run方法而使线程死亡 ③在执行wait()、sleep()方法过程中可能也会被其他对象调用它的interrupt(),没有捕获异常 新建状态 就绪状态 运行状态 阻塞状态 死亡状态

为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive()方法,如果是可运行或被阻塞,这个方法返回true;如果线程仍旧是new状态且不是可运行的,或者线程死亡了,则返回false。
sleep()和wait()区别
1.sleep()属于Thread类静态方法,wait()属于Object成员方法
2.sleep()释放cpu执行权,不会释放同步锁;wait()会释放cpu执行权和同步锁
3.sleep()需要指定时间,wait()可以指定也可以不指定时间
4.sleep()可以在任何地方使用,wait()只能在同步方法和同步代码块中使用
5.sleep()必须捕获异常,wait()可以捕获异常或者抛出异常
6.sleep()方法表示让线程进入睡眠状态,等一定时间后进入运行状态,但不会立马进入,因为线程调度机制恢复线程的运行也需要时间,一个sleep()方法被调用后,不会释放对象锁,使线程进入阻塞状态;在执行sleep()方法过程中可能被其他对象调用它的interrupt(),产生InterruptedException异常,如果你的程序不捕获这个异常,线程就会异常终止,使线程进入死亡状态
7.wait()方法如果被调用,必须要采用notify()和notifyAll()方法唤醒该线程,会释放所有对象同步锁;在执行wait()方法过程中可能也会被其他对象调用它的interrupt(),产生InterruptedException异常,如果你的程序不捕获这个异常,线程就会异常终止,使线程进入死亡状态
创建线程池有哪几种方式
1.newSingleThreadExecutor
创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
2.newFixedThreadPool(int nThreads)
创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
3.newCachedThreadPool
创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,
那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
4.newScheduledThreadPool(int corePoolSize)
创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求
线程池中 submit()和 execute()方法有什么区别
1.execute() 参数 Runnable ;submit() 参数 (Runnable) 或 (Runnable 和 泛型 T) 或 (Callable)
2.execute() 没有返回值;而 submit() 有返回值
3.submit() 的返回值 Future 调用get方法时,可以捕获处理异常
线程池有5种状态
Running、ShutDown、Stop、Tidying、Terminated
在 java 程序中怎么保证多线程的运行安全
1.原子性:提供互斥访问,同一时刻只能有一个线程对数据进行操作,(atomic,synchronized)
2.可见性:一个线程对主内存的修改可以及时地被其他线程看到,(synchronized,volatile)
3.有序性:一个线程观察其他线程中的指令执行顺序,由于指令重排序,该观察结果一般杂乱无序,(happens-before原则)
什么是死锁?
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去
怎么防止死锁?
1.互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源
2.请求和保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放
3.不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释放
4.环路等待条件:是指进程发生死锁后,若干进程之间形成一种头尾相接的循环等待资源关系
什么是反射
可以在运行时根据指定的类名获得类的信息
Object object = Class.forName(ClassName).newInstance();//创建对象,className是类的全全名
获得构造方法
Constructor getConstructor(Class[] params)//根据指定参数获得public构造器
Constructor[] getConstructors()//获得public的所有构造器
Constructor getDeclaredConstructor(Class[] params)//根据指定参数获得public和非public的构造器
Constructor[] getDeclaredConstructors()//获得public的所有构造器
获得类方法的方法
Method getMethod(String name, Class[] params);//根据方法名,参数类型获得方法
Method[] getMethods()//获得所有的public方法
Method getDeclaredMethod(String name, Class[] params)//根据方法名和参数类型,获得public和非public的方法
Method[] getDeclaredMethods()//获得所以的public和非public方法
获得类中属性的方法
Field getField(String name)//根据变量名得到相应的public变量
Field[] getFields()//获得类中所以public的方法
Field getDeclaredField(String name)//根据方法名获得public和非public变量
Field[] getDeclaredFields()//获得类中所有的public和非public方法
什么是 java 序列化?什么情况下需要序列化?
1.序列化:将 Java 对象转换成字节流的过程。
2.反序列化:将字节流转换成 Java 对象的过程。
当 Java 对象需要在网络上传输 或者 持久化存储到文件中时,就需要对 Java 对象进行序列化处理。
3.序列化的实现:类实现 Serializable 接口,这个接口没有需要实现的方法。实现 Serializable 接口是为了告诉 jvm 这个类的对象可以被序列化。
声明为 static 和 transient 的成员变量,不能被序列化。static 成员变量是描述类级别的属性,transient 表示临时数据
动态代理是什么?有哪些应用?
1.动态代理:当想要给实现了某个接口的类中的方法,加一些额外的处理。比如说加日志,加事务等。可以给这个类创建一个代理,故名思议就是创建一个新的类,这个类不仅包含原来类方法的功能,而且还在原来的基础上添加了额外处理的新类。这个代理类并不是定义好的,是动态生成的。具有解耦意义,灵活,扩展性强。
2.动态代理实现:首先必须定义一个接口,还要有一个InvocationHandler(将实现接口的类的对象传递给它)处理类。再有一个工具类Proxy(习惯性将其称为代理类,因为调用他的newInstance()可以产生代理对象,其实他只是一个产生代理对象的工具类)。利用到InvocationHandler,拼接代理类源码,将其编译生成代理类的二进制码,利用加载器加载,并将其实例化产生代理对象,最后返回。
3.动态代理的应用:Spring的AOP,加事务,加权限,加日志
怎么实现动态代理
创建接口(被代理类)

Public interface Person{
Void abc();
}

实现接口的类(被代理实现类)

public class Student implements Person{
private String name;
public Student(String name){
this.name = name;
  }
@Override
public void abc() {
	……
  }
}

创建类实现invocationHandler接口(类中有被代理类的实例对象,有一个invoke方法,所有执行代理对象的方法都会被替换成执行invoke方法)

public class StuInvocationHandler<T> implements InvocationHandler {
//invocationHandler持有的被代理对象
    T target;
    public StuInvocationHandler(T target) {
       this.target = target;
      }
    
    /**
     * proxy:代表动态代理对象
     * method:代表正在执行的方法
     * args:代表调用目标方法时传入的实参
     */
    @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	Object result = method.invoke(target, args);
	return result;
  }
}

测试:使用简化的方式创建动态代理对象

public class ProxyTest {
public static void main(String[] args) {
//创建一个实例对象,这个对象是被代理的对象
        Person zhangsan = new Student("张三");
        //创建一个与代理对象相关联的InvocationHandler
        InvocationHandler stuHandler = new StuInvocationHandler<Person>(zhangsan);
        //创建一个代理对象stuProxy来代理zhangsan,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
        Person stuProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler);
       //代理执行abc的方法
       stuProxy.abc();	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值