JAVA基础总结

特性

重载(Overload)和重写(Override)的区别是什么?

  • 重载是某个方法,可以有不同的参数列表、返回值和修饰符。在实际应用中实在是太常见了,就是比如自定义个add方法吧,这个add方法可以往数组里存一个字符串;然后我可以在他下面再写个add方法,这次可以存个字符串和int数字,这样我调用的时候就可以根据需要来传参。

  • 重写是子类继承父类时,子类想对父类的方法做出修改,就可以@Override注释,写出跟父类相同的方法体(返回值的范围可以比父类小),方法内容随意重写。

Java8的新特性你都了解哪些?

λ表达式、方法引用表达式、Stream流、新的时间类等等。

在项目中常用的λ表达式和方法引用表达式,比如对分块文件列表 进行按名称排序,就是用了λ表达式和comparingInt方法来实现的。

抽象类和接口的区别?

  1. 抽象类一般用作实体类的抽象,用abstract修饰,

    接口一般是在service层、Dao层之类的系统架构上面使用,是对动作的抽象,用interface修饰。

  2. 一个抽象类只能被单继承(extends),一个接口可以被多实现(implements)。

  3. 实现一个接口,必须实现接口中的所有方法,抽象类可以有选择地进行继承。

==equals() 的区别是什么?

  • ==是判断两个变量或实例是不是指向同一个内存空间。

    equals是判断两个变量或实例所指向的内存空间的值是不是相同。

  • ==是一个操作符,equals是一个方法。

  1. 常用的Objectequals()方法其实就是==;而Stringequals()重写了此方法,是比较对象的值。.所以equals()方法有没有被重写是判断其与==的区别的主要关注点。

阐述final、finally、finalize的区别

final

  • final是一个修饰符,意为最终态。如果一个类被声明为final,意味着它不能再派生新的子类。(因此一个类不能既被声明为abstract,又被声明为final的,因为abstract是抽象的,要使用它必须要去继承。)

  • 将变量或方法声明为final,可以保证他们使用中不被改变。被声明为final的变量必须在声明时给定初值,而以后的引用中只能读取,不可修改,被声明为final的方法也同样只能使用,不能重载。

finally:

  • 在异常处理时提供finally块来执行终结操作,即无论try/catch执行结果如何,都会在之后执行finally块里面的代码。

finalize

  • finalize()是Object中的方法,当垃圾回收器将要回收对象所占内存之前被调用,即当一个对象被虚拟机宣告死亡时会先调用finalize()方法,让此对象处理它生前的最后事情(等于是下了一个最终通牒)。

String 类的常用方法都有那些?

length(),equals(),getByte(),转换大小写,trim(),subString(int)等等。

break和continue有什么区别??

用break语句可以使流程跳出switch语句体,也可以用break语句在循环结构终止本层循环体,从而提前结束本层循环。

continue是结束本次循环,继续下一次循环。

数据类型

StringStringBufferStringBuilder的区别是什么?

String是一个用final修饰的字符数组,是一个不可变的对象。每次修改字符串对象时都等同于生成了一个新的对象,然后将指针指向新对象。

StringBufferStringBuilder是可变的字符序列,都在原来的对象的本身进行操作;

StringBuffer是线程安全;StringBuilder是线程不安全的,但是StringBuilder的速度是比StringBuffer快的。

总体的速度比较上,大部分情况下StringBuilder>StringBuffer>String

intInteger的区别?

首先最本质的区别就是,int类型是一个数据基本类型,而Integer是一个基本类型的包装类。

由此就能得出以下几点区别:

  1. int是直接存储数据值,而Integer是对象的引用。(当new一个Integer时,实际上是生成一个指针指向此对象)

  2. Integer变量必须实例化后才能使用,而int变量不需要。

  3. int默认值为0,Integer默认值为null。

集合

你平常用过哪些集合?

常用的就是ArrayList,LinkedList,HashMap,其他的还有TreeMap,HashTable,TreeSet,HashSet等。

List、set、map他们的区别?

首先,ListSet都是Collection下的子接口,而Map是与Collection同级的接口。

  • Set接口最重要的一点是不包含重复元素,而且是无序的。而他下面的TreeSet实现了有序。

  • List接口允许重复元素,并且是保证顺序的,可以插入null元素,其下面常用的有LinkedListArrayList

  • Map是通过键值对的方式存储数据,每一个键都可以获取唯一对应的值。

LinkedList和ArrayList的区别?

ArrayList

  • 底层数据结构是数组
  • 由于其存放数据的是一块连续的内存空间,就可以根据数组的首地址加上偏移量,直接计算出第n个元素在内存中的位置,所以它查询快
  • 增删慢:还是由于其数据结构的原因,当想要在中间插入一条数据时,后面的数据需要全部往后挪一位,甚至是要将新数组重新分配内存空间。

LinkedList

  • 底层数据结构是双向链表
  • LinkedList存放数据是分散的,每一个数据保存自身数据+下一个数据的内存地址查询时要从头部顺着链子依次查,所以它查询慢
  • 增删快:LinkedList想要插入数据,只需要将插入位置断开,就像自行车链条一样,安插进去,修改的只是节点之间的引用。

Arraylist为什么线程不安全?怎么解决?

ArrayList添加数据时,会分为两步:存放数据和修改size。当存放数据后线程被抢,然后另一线程也存放数据,就会导致存放数据实际只有一条,而size为2。

解决方法:1. 使用synchronized关键字。2. 使用Collections类提供的synchronizedList()方法。

怎么删除list中的某个数据?

  1. 暴力for循环遍历,调用remove
  2. 原list叫listA,将某个数据存为另一个listB,listA调用removeAll方法,删除listB
  3. 得到该list的迭代器,使用迭代器的remove方法。

Java的队列有了解吗?

队列即Queue,是与List,Set同一级别的接口。LinkedList实现了Queue接口下的子接口Deque(双端队列)。

没有实现阻塞接口的有:LinkedList,PriorityQueueConcurrentLinkedQueue

实现阻塞接口的:ArrayBlockingQueue(基于数组的有界队列),LinkedBlockingQueue(基于链接的有界队列),PriorityBlockingQueue(基于优先级的无界队列),DelayQueueSynchronousQueue

HashMap

HashMap底层结构是什么?

JDK1.7是HashMap的底层结构是链表+数组JDK1.8是数组+链表+红黑树。HashMap如果在创建时没有指定容量,默认初始容量为16。扩容阈值为数组长度的0.75,每次扩充容量翻倍。当HashMap长度小于8时使用链表,而当HashMap长度大于8时自动转化为红黑树。

HashMap是否是线程安全的?如何保证HashMap线程安全?

HashMap不是线程安全的。

  • 使用Collection类里面的synchronizedMap()包装一下,即可得到线程安全的map;(使用的是悲观锁)

  • 使用ConcurrentHashMap类,可以直接得到一个线程安全的HashMap(采用的是乐观锁)

HashMap为什么初始化大小为16?

HashMap的初始化大小是将初始化大小二进制按位与,而扩容机制是HashMap每次扩容都是以 2的整数次幂进行扩容。因此最合适的初始化大小是16,4和8理论上也可以,但是因为太小容易导致map扩容影响性能;太大浪费资源。

总结就是:

  1. 减少hash碰撞。

  2. 提高map查询效率。

  3. 分配过小防止频繁扩容。

  4. 分配过大浪费资源。

HashMap怎么进行扩容?

HashMap如果在创建时没有指定容量,默认初始化大小为16。HashMap每次扩容都是以 2的整数次幂进行扩容。

红黑树和链表怎么进行转化?

当HashMap长度小于8时使用链表,而当HashMap长度大于8时自动转化为红黑树。目的是为了减少搜索时间

纯链表的平均查找长度为(n+1)/2,红黑树平均查找长度则为log2n。 长度为8的时候,红黑树平均查找长度为3,链表平均查找长度为8/2=4,这才有转换为树的必要。链表长度如果是小于等于6, 6/2=3,速度已经很快,并且转化为树结构和生成树的时间不会很短,所以没必要转成红黑树。

HashMap和TreeMap的区别?

  1. 实现
    HashMap基于哈希表;
    TreeMap基于红黑树。
  2. 存储和遍历
    HashMap随机存,随机遍历;
    TreeMap升序存,排序遍历。
  3. 性能损耗
    HashMap基本无损耗;
    TreeMap插入删除速度慢,需要维护树的平衡。
  4. 键值对
    HashMap键、值均可为null;
    TreeMap键、值均不可为null。
  5. 安全性和效率
    HashMap不安全,效率高;
    TreeMap不安全,效率低。

HashMap和Hashtable有什么区别?

HashMap线程不安全,效率高,键值允许null,非同步,适合单线程环境;
Hashtable线程安全,效率低,不允许null键值,同步,适合多线程。
但是多线程环境下仍不建议使用HashTable,因为
1. HashTable是遗留类,内部实现很多没有优化,冗余多,
2. 内部全部加了Syn锁,重量级锁,效率低,
3. 多线程有了更好的同步的ConcurrentHashMap替代。

HashMap和LinkedHashMap有什么区别?

HashMap是最常用的一个Map,根据key的hash值来存储数据,底层是链表+红黑树,当长度小于8时使用链表,大于8时自动转化为红黑树。HashMap是线程不安全的,如果需要线程安全,可以使用Collections.synchronizedMap()来获取一个线程安全的map;也可以直接使用ConcurrentHashMap类来获取一个线程安全的HashMap。

LinkedHashMap是HashMap下面一个子类,跟HashMap的区别就是HashMap是无序的,而LinkedHashMap是可以保存插入顺序的。当对输出顺序有要求的话可以使用LinkedHashMap。一般而言LinkedHashMap的性能会比HashMap差一点(特殊情况:HashMap容量大而实际数据少时会比LinkedHashMap差,因为LinkedHashMap遍历速度只与实际数据有关,而HashMap与容量也有关)

SynchronizedVolatile的区别是什么?

  1. synchronized 可以作用于变量、方法、对象;volatile 只能作用于变量。

  2. synchronized 可以保证线程间的有序性、原子性和可见性;
    volatile 只保证了可见性和有序性,无法保证原子性。

  3. synchronized 有可能导致线程阻塞,volatile 线程不阻塞。

  4. volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化。

线程

进程和线程的区别?

进程就等于是电脑里运行的程序,线程就等于是可以让一个进程同时执行多个任务,一个进程可以有多个线程。

java里面创建线程的方式

  1. 实现Runnable接口的run()方法 ,然后通过Threadstart()方法开启线程。
  2. 继承Thread类,重写run()方法,这个本质上与实现Runnable接口的方式一致,因为Thread类本身就实现了Runnable接口。
  3. 实现Callable接口的call()方法,然后通过Futureget()方法进行开启线程。与另外两个的区别是这个有返回值。
  4. 通过JUC里面的线程池。

Java中的线程池是什么,有哪些常用的参数?

线程池的基本功能就是进行线程的复用,当程序需要一个线程时,会先从线程池里面捞一下空闲线程来使用;用完后会将线程重新放入线程池。

corePoolSize:池中所保存的常驻线程数。

maximumPoolSize:池中允许的最大线程数。

keepAliveTime: 多余的空闲线程最多存活时间。

unit: keepAliveTime的单位。

handler:拒绝策略,表示当队列满了,如何拒绝。java默认提供了4种饱和策略的实现方式:中止、抛弃、抛弃最旧的、调用者运行。

workQueue:任务队列。

threadFactory :表示生成线程池中工作线程的线程工厂。
……

常用线程池?

  1. newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
  2. newFixedThreadPool :创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  3. newScheduledThreadPool: 创建一个定长线程池,支持定时及周期性任务执行。
  4. newSingleThreadExecutor :创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

线程池创建方式?

  1. 使用ThreadPoolExecutor类

  2. 使用Executors类

其实这两种方式在本质上是一种方式,都是通过ThreadPoolExecutor类的方式。

线程池的优点?

  1. 重用存在的线程,减少对象创建、消亡的开销,性能佳。

  2. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。

  3. 提供定时执行、定期执行、单线程、并发数控制等功能。

    1. 降低资源消耗: 重复利用线程,减少创建和销毁造成的消耗。

    2. 提升响应速度: 任务到达,不需要创建,立即执行。

    3. 提高可管理型: 线程是CPU调度和分派的基本单位。

服务端同步和异步你是怎么理解的?

同步在一定程度上可以看做是单线程,这个线程请求一个方法后就待这个方法给他回复,否则他不往下执行(死心眼)。

异步在一定程度上可以看做是多线程的(废话,一个线程怎么叫异步),请求一个方法后,就不管了,继续执行其他的方法。


同步,可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是处于阻塞的,只有接收到返回的值或消息后才往下执行其他的命令。

异步,执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程,那么当系统接收到返回值或消息时,系统会自动触发委托的异步过程,从而完成一个完整的流程。


同步,就是实时处理,比如服务器一接收客户端请求,马上响应,这样客户端可以在最短的时间内得到结果,但是如果多个客户端,或者一个客户端发出的请求很频繁,服务器无法同步处理,就会造成涌塞。

异步,就是分时处理,服务器接收到客户端请求后并不是立即处理,而是等待服务器比较空闲的时候加以处理,可以避免涌塞。


同步就是调用一个函数,直接函数执行完了才返回到调用函数;

异步就是被调用函数初始化完后马上返回。

JVM

链接:jvm内存模型、常见参数及调优

分别解释一下栈和堆?

栈是运行时的单位,解决程序如何执行,代表处理逻辑

堆是存储单位,解决数据存储问题,代表数据

JVM类加载机制,调优机制是什么?

  • JVM类加载机制

    JVM类加载机制分为五个部分:加载验证准备解析初始化

    虚拟机将class文件加载到内存,并对数据校验、准备和解析,之后完成初始化。

    加载就是JVM将字节码文件转化为二进制字节流加载到内存中,然后为这个类在JVM方法区创建一个Class对象(访问入口);

    验证是连接阶段的第一步,这一步主要就是为了确保class文件符合虚拟机的要求;

    准备阶段是最重要的,这个阶段会为类变量分配内存初始化。(类变量就是带static修饰的变量,而类成员变量是不带static修饰的,类成员变量的内存分配时机是初始化阶段。)初始化时会为类变量赋予其数据类型的零值,而不是代码里初始化的值,例如:

    public static int number = 3;
    public  static final finalNumber = 3;
    

    这里的number初始化值是0,而不是3。

    但如果其被final修饰,即成为了常量,那么在准备阶段就会被赋值为3,好比这里的finalNumber的值为3。

    解析阶段会将常量池内的符号引用替换为直接引用。

    1. 符号引用:简单的理解就是字符串,比如引用一个类,java.util.ArrayList 这就是一个符号引用,字符串引用的对象不一定被加载。
    2. 直接引用:指针或者地址偏移量。引用对象一定在内存(已经加载)。

    初始化阶段会执行类构造器的clinit()方法,为类变量赋予正确的初始值(之前在准备阶段只是分配空间并赋予0值,现在才赋予正确值),而初始值设定有两种方法:

    1. 直接声明类变量的指定初始值,比如上面的number=3,就是此时赋予;
    2. 使用静态代码块进行指定初始值。
  • 调优机制

    对JVM内存的系统级的调优主要的目的是减少GC的频率Full GC的次数,过多的GC和Full GC是会占用很多的系统资源(主要是CPU),影响系统的吞吐量。

    1. 老年代空间不足:(会引起Full GC)
      • 尽量让对象在年轻代GC时被回收;
      • 让对象在年轻代多存活一段时间;
      • 不要创建过大的对象;
      • 数组避免直接在老年代创建对象。
    2. 年轻代空间不足:
      • 增大年轻代空间,避免太多静态对象;
      • 控制好年轻代和老年代的比例;
    3. 垃圾回收尽量不要手动触发 ,尽量依靠JVM自身的机制。

    调优手段主要是通过控制堆内存的各个部分的比例和GC策略

双亲委派模型的工作流程是什么?

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。

(就是儿子能干也不干,先让爸爸干,爸爸想偷懒就让爷爷干。爷爷能干就干,不能干就还推给爸爸干)。

双亲委派机制可以被打破吗?

可以

  1. 自定义类加载器,重写loadClass方法;
  2. 使用线程上下文类加载器。

使用PC寄存器记录当前线程的执行地址有什么用?

因为CPU需要不停的起换各个线程,这时候切换回来以后,就得知道接从哪哪开始继续执行

GC分为几种?

  • Minor GC
  • Full GC
  • Major GC 是清理永久代 通常至少经历过一次Minor GC

GC发生在哪里?

堆。

怎么判定垃圾?

  • 引用计数法
  • 可达性分析

设计模式

单例设计模式

  • 饿汉式

    1. 私有化构造器
    2. 内部创建对象
    3. 提供公共静态方法,返回对象

    优点:线程安全

    缺点:加载时间长

    class Singleton {
        // 私有化构造器
        private Singleton(){}
        // 内部创建对象
         private static Singleton instance = new Singleton();
        // 对外提供静态方法返回对象
        public static Singleton getInstance() {
            return instance;
        }
    }
    
  • 懒汉式

    1. 私有化构造器
    2. 内部声明对象,没有初始化
    3. 提供公共静态方法,返回对象

    优点:延迟对象的创建,节约内存空间

    缺点:线程不安全(可以通过加锁改进为安全)

    class Singleton {
    	// 私有化构造器
    	private Singleton(){}
        // 内部声明对象,没有初始化
        private static Singleton instance=null;
        //提供公共静态方法,返回对象 
    	public static Singleton getInstance() {
    		if(instance == null){
                instance = new Singleton();
            }
    		return instance;
        }
    }
    

    线程安全的懒汉式:

    //懒汉式线程安全
    class Singleton{
        private Singleton(){};
        private static Singleton instance = null;
        public static Singleton getInstance(){
            if(instance == null) {
                synchronized (Singleton.class) {
                    if (instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

Web

post 和 get请求的区别?

get:从服务器上获取数据,可以从url上面进行传参,传递数据量较小,安全性低;

post:是通过报文来传递数据,一般传递一些表单、json数据等大量的数据,安全性高。

还有一点是:get产生一个TCP包,post先发送header,服务器响应后再发送data,因此产生两个数据包。

在做数据查询时,建议用Get方式;而在做数据添加、修改或删除时,建议用Post方式

JSP的内置对象有哪些?

名称介绍
requestrequest
responseresponse
sessionsession对象指的是客户端与服务器的一次会话,从客户连到服务器开始,直到与服务器断开连接为止。
outout是向客户端输出内容常用的对象
pagepage对象就是指向当前JSP页面本身,有点象类中的this指针。
applicationapplication对象实现了用户间数据的共享,可存放全局变量。服务器的启动和关闭决定application对象的生命。
exceptionexception
pageContextpageContext对象提供了对JSP页面内所有的对象及名字空间的访问。
configconfig

JSP的四大作用域及其范围

名称作用域
application在所有应用程序中有效
session在当前会话中有效
request在当前请求中有效
page在当前页面有效
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小九网创

记得私信我,得源码

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值