lcx-java基础

1.集合有哪些?数据结构?初始长度?扩容机制?哪些是线程安全的?hashmap的底层原理?

集合类型主要有3种:set(集)、list(列表)和map(映射)。

1、List(有序、可重复)

List里存放的对象是有序的,同时也是可以重复的,List关注的是索引,拥有一系列和索引相关的方法,查询速度快。因为往list集合里插入或删除数据时,会伴随着后面数据的移动,所有插入删除数据速度慢。

2、Set(无序、不能重复)

Set里存放的对象是无序,不能重复的,集合中的对象不按特定的方式排序,只是简单地把对象加入集合中。

3、Map(键值对、键唯一、值不唯一)

Map集合中存储的是键值对,键不能重复,值可以重复。根据键得到值,对map集合遍历时先得到键的set集合,对set集合进行遍历,得到相应的值。

Set接口数据结构

哈希表存储结构

List

有序可重复

ArrayList

ArrayList数据结构是数组查询快,增删慢。ArrayList是线程不安全的,允许元素为null 。

Vector

线程安全的数组,效率较差,已经过时不用。

LinkedList

LinkedList 数据结构是双向链表,插入删除比较方便。LinkedList 是线程不安全的,允许元素为null 。

Map

HashMap :

jdk1.8中HashMap底层是哈希表数据结构,数组+链表+红黑树,HashMap是线程不安全的,允许使用null键和null值,

HashMap根据键的HashCode值存储数据,具有很快的访问速度。

HashMap存入的键值对在遍历时的顺序是随机的。

HashMap不支持并发

HashTable:

线程安全使用synchronized锁住全部数据,效率较低。

LinkedHashMap:

LinkedHashMap 是HashMap的一个子类,默认LinkedHashMap遍历时输出的顺序和put输入的顺序是相同的。

LinkedHashMap有两种排序方式:插入排序和访问排序(修改或访问一个元素后,将该元素移到队列末尾),默认是插入排序。使用accessOrder来标记使用哪种排序方式,accessOrder==true时,表示使用访问排序,默认为false;

LinkedHashMap使用了双向链表来保证了顺序性。

TreeMap:

TreeMap底层是红黑树数据结构,线程不安全,可以用于给Map集合中的键进行排序

TreeMap遍历出来的是排序后的键值对。

ConcurrentHashMap

ConcurrentHashMap是线程安全的,jdk1.8使用CAS和volatile实现。而jdk1.8以前通过锁分段技术、可重入锁实现。

支持并发,可以一边更新一边遍历

初始长度 扩容机制

线程安全和线程不安全的集合

Vector、HashTable、Properties是线程安全的;

ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等都是线程不安全的。

值得注意的是:为了保证集合是线程安全的,相应的效率也比较低;线程不安全的集合效率相对会高一些。


HashMap 的实现原理?

HashMap的put()和get()的实现

map.put:

1.调用hashcode方法得出hash值  2.通过哈希算法转化成下标  3.下标位置上如果没有任何元素,就把Node添加到这个位置上  4.如果对应位置有链表 用key和链表上的key进行equals  5.如果map.put返回值都为false添加到末尾 如果有为true的 覆盖value

map.get:

1.调用hashcode方法得出hash值  2.通过哈希算法转化成下标  3.下标位置上如果没有任何元素,就返回null  4.如果对应位置有链表 用key和链表上的key进行equals  5.如果map.get 都是false则返回null 如果有true就返回对应value

2.线程的创建?开启?状态? sleep和wait的区别?线程池?死锁?如何保证线程安全

创建线程有哪几种方式?

①.继承Thread类创建线程类

定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。

创建Thread子类的实例,即创建了线程对象。

调用线程对象的start()方法来启动该线程。

②. 通过Runnable接口创建线程类

定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。

创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。

调用线程对象的start()方法来启动该线程。

③. 通过Callable和Future创建线程

创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。

创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。

使用FutureTask对象作为Thread对象的target创建并启动新线程。

调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。

调用线程对象的start()方法来启动该线程

线程有哪些状态?

线程通常都有五种状态,创建、就绪、运行、阻塞和死亡

创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态

就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。

运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。

阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞

死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪

sleep() 和 wait() 有什么区别?

sleep():线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象

wait():同时释放对象的机锁,使得其他线程能够访问

创建线程池有哪几种方式?

①. newFixedThreadPool(int nThreads)

创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的线程。

②. newCachedThreadPool()

创建一个可缓存的线程池,如果线程池的规模超过了处理需求,将自动回收空闲线程,而当需求增加时,则可以自动添加新线程,线程池的规模不存在任何限制。

③. newSingleThreadExecutor()

这是一个单线程的Executor,它创建单个工作线程来执行任务,如果这个线程异常结束,会创建一个新的来替代它;它的特点是能确保依照任务在队列中的顺序来串行执行。

④. newScheduledThreadPool(int corePoolSize)

创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于Timer。

什么是死锁?

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者进程在运行过程中,请求和释放资源的顺序不当而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程

怎么防止死锁?

加锁顺序(线程按照一定的顺序加锁)

加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)

死锁检测

在 java 程序中怎么保证多线程的运行安全?

1、使用线程安全的类;

2、使用synchronized同步代码块,或者用Lock锁;

3、多线程并发情况下,线程共享的变量改为方法局部级变量;

3.==和 equals的区别?

== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals 默认情况下是引用比较,只是很多类重新了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。

4.对反射的理解?获取 Class类的方式有哪些?如何用反射取私有属性 Filed?

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性方法;对于任意一个对象,都能够调用它的任意一个方法属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

获取Class对象的三种方式

第一种,使用 Class.forName 静态方法。

前提:已明确类的全路径名。

第二种,使用 .class 方法。

说明:仅适合在编译前就已经明确要操作的 Class

第三种,使用类对象的 getClass() 方法。

适合有对象示例的情况下

如何用反射取私有属性?

利用反射,首先是Class字节码对象的获取,

// 获得指定类的属性

Field field = clazz.getDeclaredField("name");

// 值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。

field.setAccessible(true);取消 Java 语言访问检查

5.常用设计模式有哪些?在项目中哪里有用到?单例中懒汉饿汉优缺点?

单例模式

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建

装饰者模式

已有的业务逻辑进一步的封装,使其增加额外的功能

工厂模式

一个抽象的接口多个抽象接口的实现类,一个工厂类,用来实例化抽象的接口

单例中懒汉饿汉优缺点

1.饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不在改变。懒汉式如果在创建实例对象时不加上synchronized则会导致对对象的访问不是线程安全

2.从实现方式来讲他们最大的区别就是懒汉式是延时加载,他是在需要的时候才创建对象,而饿汉式在虚拟机启动的时候就会创建,饿汉式无需关注多线程问题,写法简单明了,能用则用。真正用到的时候才去建这个单例对象,“饿汉式”是在不管用不用得上,一开始就建立这个单例对象。

懒汉式是典型的时间换空间,也就是每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间。当然,如果一直没有人使用的话,那就不会创建实例,则节约内存空间

饿汉式是典型的空间换时间,当类装载的时候就会创建类实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断了,节省了运行时间

6.JDK1.8中有哪些新特性?

Lambda表达式:Lambda允许把函数作为一个方法的参数(函数作为参数传递到方法中)。

语法形式为 () -> {},其中 () 用来描述参数列表,{} 用来描述方法体,-> 为 lambda运算符 ,读作(goes to)。

Default关键字:通过使用default修饰方法,可以让我们在接口里面定义具体的方法实现 接口的实现类实现了这个接口之后,可以直接调用

方法引用:方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

Date Time API:加强对日期与时间的处理。

Optional类:Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。

7. session的实现原理? session的生命周期? session如何存储数据?

session的实现原理

当客户端访问服务器时,服务器根据需求设置session,将会话信息保存在服务器上,同时将标示session的session_id传递给客户端浏览器,浏览器将这个session_id保存在内存中(还有其他的存储方式,例如写在url中),我们称之为无过期时间的cookie。浏览器关闭后,这个cookie就清掉了,它不会存在用户的cookie临时文件。以后浏览器每次请求都会额外加上这个参数值,再服务器根据这个session_id,就能取得客户端的数据状态

如果客户端浏览器意外关闭,服务器保存的session数据不是立即释放,此时数据还会存在,只要我们知道那个session_id,就可以继续通过请求获得此session的信息;但是这个时候后台的session还存在,但是session的保存有一个过期时间,一旦超过规定时间没有客户端请求时,他就会清除这个session

session的生命周期

Session存储在服务器的内存中(为了高速存取)。

Session何时生效

Sessinon在用户访问第一次访问服务器时创建,需要注意只有访问JSP、Servlet等程序时才会创建Session,只访问HTML、IMAGE等静态资源并不会创建Session,可调用request.getSession(true)强制生成Session。

Session何时失效

服务器会把长时间没有活动的Session从服务器内存中清除,此时Session便失效。Tomcat中Session的默认失效时间为20分钟。


Java中的session存储

sessionid是一个会话的key,浏览器第一次访问服务器会在服务器端生成一个session,有一个sessionid和它对应。tomcat生成的sessionid叫做jsessionid。

session在访问tomcat服务器HttpServletRequest的getSession(true)的时候创建,tomcat的ManagerBase类提供创建sessionid的方法:随机数+时间+jvmid。

存储在服务器的内存中,tomcat的StandardManager类将session存储在内存中,也可以持久化到file,数据库,memcache,redis等。客户端只保存sessionid到cookie中,而不会保存session,session销毁只能通过invalidate或超时,关掉浏览器并不会关闭session。

8.类加载机制?代码块的执行顺序?

类加载分为三个步骤:加载、连接、初始化。

1.加载

类加载指的是将class文件读入内存,并为之创建一个java.lang.Class对象,即程序中使用任何类时,系统都会为之建立一个java.lang.Class对象,系统中所有的类都是java.lang.Class的实例。

类的加载由类加载器完成,JVM提供的类加载器叫做系统类加载器,此外还可以通过继承ClassLoader基类来自定义类加载器。

通常可以用如下几种方式加载类的二进制数据:

从本地文件系统加载class文件。

从JAR包中加载class文件,如JAR包的数据库启驱动类。

通过网络加载class文件。

把一个Java源文件动态编译并执行加载。

2.连接

连接阶段负责把类的二进制数据合并到JRE中,其又可分为如下三个阶段:

验证:确保加载的类信息符合JVM规范,无安全方面的问题。

准备:为类的静态Field分配内存,并设置初始值。

解析:将类的二进制数据中的符号引用替换成直接引用。

3.初始化

该阶段主要是对静态Field进行初始化,在Java类中对静态Field指定初始值有两种方式:

声明时即指定初始值,如static int a = 5;

使用静态代码块为静态Field指定初始值,如:static{    b = 5;    }

JVM初始化一个类包含如下几个步骤:

假如这个类还没有被加载和连接,则程序先加载并连接该类。

假如该类的直接父类还没有被初始化,则先初始化其直接父类。

假如类中有初始化语句,则系统依次执行这些初始化语句。

所以JVM总是最先初始化java.lang.Object类。

类初始化的时机(对类进行主动引用时):

创建类的实例时(new、反射、反序列化)。

调用某个类的静态方法时。

使用某个类或接口的静态Field或对该Field赋值时。

使用反射来强制创建某个类或接口对应的java.lang.Class对象,如Class.forName("Person")

初始化某个类的子类时,此时该子类的所有父类都会被初始化。

直接使用java.exe运行某个主类时。

代码块的执行顺序?

静态代码块 >>> 构造代码块 >>>> 构造方法

如果有继承的话

父类静态代码块>>>子类的静态代码块>>>父类的构造代码块>>>父类的构造方法>>>子类的构造代码块>>>子类的构造方法

9. cookie和 session的区别?

cookie保存在客户端,session保存在服务器端,

cookie目的可以跟踪会话,也可以保存用户喜好或者保存用户名密码

session用来跟踪会话

10.java中字符串的方法有哪些? string stringbuild stringbuffer的区别

1、equals():比较两个字符串是否相等

2、equalsIgnoreCase( ):忽略大小写的两个字符串是否相等比较

3、toString():转换成String类型

4、equalsIgnoreCase( ):忽略大小写的两个字符串是否相等比较

5、String.valueOf():转换成String类型(不用担心object是否为null值这一问题)

6、split():分隔符

7、subString():截取字符串中的一段字符串

8、charAt():返回指定索引处char值

9、toLowerCase():将所有在此字符串中的字符转化为小写(使用默认语言环境的规则)

10、indexOf():指出 String 对象内子字符串的开始位置

11、replace和replaceAll

12、getBytes():得到一个系统默认的编码格式的字节数组

string stringbuild stringbuffer的区别

String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String

StringBuffer 和 StringBuilder 最大的区别在于,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的,但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder多线程环境下推荐使用 StringBuffer

11.jvm调优和垃圾回收机制?

JVM调优目标:使用较小的内存占用来获得较高的吞吐量或者较低的延迟

程序在上线前的测试或运行中有时会出现一些大大小小的JVM问题,比如cpu load过高、请求延迟、tps降低等,甚至出现内存泄漏(每次垃圾收集使用的时间越来越长,垃圾收集频率越来越高,每次垃圾收集清理掉的垃圾数据越来越少)、内存溢出导致系统崩溃,因此需要对JVM进行调优,使得程序在正常运行的前提下,获得更高的用户体验和运行效率。

这里有几个比较重要的指标:

内存占用:程序正常运行需要的内存大小。

延迟:由于垃圾收集而引起的程序停顿时间。

吞吐量:用户程序运行时间占用户程序和垃圾收集占用总时间的比值。

当然,和CAP原则一样,同时满足一个程序内存占用小、延迟低、高吞吐量是不可能的,程序的目标不同,调优时所考虑的方向也不同,在调优之前,必须要结合实际场景,有明确的的优化目标,找到性能瓶颈,对瓶颈有针对性的优化,最后进行测试,通过各种监控工具确认调优后的结果是否符合目标。

2、JVM调优工具

调优可以依赖、参考的数据有系统运行日志堆栈错误信息、gc日志、线程快照、堆转储快照等。

垃圾回收机制

gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存

如何将垃圾回收?

在Java中存在着四种垃圾回收算法,标记清除算法、复制算法、标记整理算法以及分代回收算法。

标记清除算法

该算法分为“标记”和“清除”两个阶段:标记阶段的任务是标记出所有需要被回收的对象,清除阶段就是回收被标记的对象所占用的空间。

复制算法

它可以将内存分为大小相同的两块,每次使用其中的一块。当第一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。

标记整理算法

该算法标记阶段和标记清除一样,但是在完成标记之后,它不是直接清理可回收对象,而是将存活对象都向一端移动,然后清理掉端边界以外的内存。

分代收集算法

当前虚拟机的垃圾收集都采用分代收集算法,这种算法就是根据具体的情况选择具体的垃圾回收算法。一般将 java 堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法

(1)新生代-复制 回收机制

对于新生代区域,由于每次 GC 都会有大量新对象死去,只有少量存活。因此采用 复制 回收算法,GC 时把少量的存活对象复制过去即可。但是从上面我们可以看到,新生代也划分了三个部分比例:Eden:S1:S2=8:1:1。

其中 Eden 意为伊甸园,形容有很多新生对象在里面创建;S1和S2中的S表示Survivor,为幸存者,即经历 GC 后仍然存活下来的对象。

工作原理如下:

首先,Eden对外提供堆内存。当 Eden区快要满了,触发垃圾回收机制,把存活对象放入 Survivor A 区,清空 Eden 区;Eden区被清空后,继续对外提供堆内存;当 Eden 区再次被填满,对 Eden区和 Survivor A 区同时进行垃圾回收,把存活对象放入 Survivor B区,同时清空 Eden 区和Survivor A 区;当某个 Survivor区被填满,把多余对象放到Old 区;当 Old 区也被填满时,进行 下一阶段的垃圾回收。下面看看老年代的垃圾回收。

(2)老年代-标记整理 回收机制

老年代的特点是:存活对象多、垃圾少。因此,根据老年代的特点,这里仅仅通过少量地移动对象就能清理垃圾,而且不存在内存碎片化。也就是标记整理的回收机制。既然是标记整理算法,而且老年代内部也不存在着内存划分,所以只需要根据标记整理的具体步骤进行垃圾回收就好了。

到了这,基本上对堆内存的分代回收机制进行了描述。但是要有一个问题没有解决,那就是jvm提供的垃圾回收器。

什么是垃圾?垃圾指所有不再存活的对象

常见的判断是否存活有两种方法:引用计数法可达性分析

引用计数法

为每一个创建的对象分配一个引用计数器,用来存储该对象被引用的个数。当该个数为零,意味着没有人再使用这个对象,可以认为“对象死亡”。但是,这种方案存在严重的问题,就是无法检测“循环引用”:当两个对象互相引用,即时它俩都不被外界任何东西引用,它俩的计数都不为零,因此永远不会被回收。而实际上对于开发者而言,这两个对象已经完全没有用处了。

因此,Java 里没有采用这样的方案来判定对象的“存活性”。

可达性分析

基本思路是把所有引用的对象想象成一棵树从树的根结点 GC Roots 出发持续遍历找出所有连接的树枝对象,这些对象则被称为“可达”对象,或称“存活”对象其余的对象则被视为“死亡”的“不可达”对象,或称“垃圾”

12.java中锁的种类和基本原理?

1、分类

(1)乐观锁/悲观锁

(2)独享锁/共享锁

(3)互斥锁/读写锁

(4)可重入锁

(5)公平锁/非公平锁

(6)分段锁

(7)偏向锁/轻量级锁/重量级锁

(8)自旋锁

总结:以上是一些锁的名词,这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计。

2、基本原理

2.1 :乐观锁/悲观锁

(1)乐观锁与悲观锁是从设计理念上来分类的。

乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS(Compare and Swap 比较并交换)实现的。

(2)悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改自己的数据,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。比如Java里面的同步synchronized关键字的实现就是悲观锁。悲观锁适合写操作非常多的场景,乐观锁适合读操作非常多的场景,不加锁会带来大量的性能提升。

2.2:独享锁/共享锁

(1) 独享锁是指该锁一次只能被一个线程所持有,Java ReentrantLock就是独享锁,Synchronized也是独享锁。

(2)共享锁是指该锁可被多个线程所持有,Java ReadWriteLock其读锁是共享锁,其写锁是独享锁,读锁的共享锁可保证并发读是非常高效的,读写,写读,写写的过程是互斥的。

(3)独享锁与共享锁也是通过AQS来实现的,通过实现不同的方法,来实现独享或者共享。

(4)独享锁/共享锁是一种广义的说法。

2.3:互斥锁/读写锁

(1)互斥锁/读写锁是具体的实现。

(2)互斥锁在Java中的具体实现就是ReentrantLock,读写锁在Java中的具体实现就是ReadWriteLock。

2.4:可重入锁

可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁,ReetrantLock和Synchronized都是可重入锁。

13. collection和 collections的区别?

java.util.Collection 是一个集合接口(集合类的一个顶级接口)。

Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。

14.java如何跳出循环?

continue:跳出本次循环,继续下一次循环,也就是不执行本次循环continue下面的语句。

break:跳出本层循环,也就是这个循环体的结束。

如何跳出多层循环呢?

可以使用break来实现。使用break loop直接跳出loop循环。

return:跳出这个方法

15.java排序有哪些?原理是什么?

冒泡排序

冒泡排序顾名思义就是像开水一样不断冒泡泡。简单地说,如果是将元素从小到大排序,每次就冒出一个最大的元素,放在数组的最后面。怎样保证冒一次泡后最大的元素就放在最后面了呢?冒泡排序是通过交换相邻元素来实现的。

快速排序算法通过多次比较和交换来实现排序,其排序流程如下: [2]

(1)首先定一个分界,通过该分界值将数组分成左右两部分。 [2]

(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。 [2]

(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。 [2]

(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。

选择排序

选择排序的思想:假如我们要从小到大排序,假设第一个元素arr[0]是最小的元素,然后将arr[0]与之后的所有元素依次比较谁小谁就到前面来,遍历完以后整个数组中最小的元素就在arr[0]这个位置上了。再从arr[1]开始假设arr[1]是最小的元素,arr[1]与之后所有的元素依次比较,谁小就到arr[1]这个位置上来。依次类推,当arr[arr.length-2]这个位置元素确定时,最后一个元素就在最后一个位置了,排序结束了

16.什么是堆栈?什么是内存溢出?有垃圾回收机制为什么还会出现内存溢出的情况?

堆栈就是只能在一端插入和删除数据的链表,这个端就叫做栈顶(top),最后一个添加的数据第一个被删除。因此,这也叫后进先出(LAST IN FIRST OUT)链表或是先进后出链表(FIRST IN LAST OUT)。

内存溢出(Out Of Memory,简称OOM)是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于能提供的最大内存。此时程序就运行不了,系统会提示内存溢出

有垃圾回收机制为什么还会出现内存溢出的情况?

内存资源是有限的,垃圾回收只回收垃圾,对于你的程序运行有用的对象不会被回收。

内存溢出分两种情况一种是栈溢出,比如调用了一个无限递归。还有一种是堆溢出,即new出来的对象没有即使销毁,比如一直new

17.内存模型的理解?

18.泛型的理解?(泛型擦除)

泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?

顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),

然后在使用/调用时传入具体的类型(类型实参)。

泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,

操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。

泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。

擦除是将泛型类型以其父类代替,如String 变成了Object等。其实在使用的时候还是进行带强制类型的转化,只不过这是比较安全的转换,因为在编译阶段已经确保了数据的一致性

19.java的基本类型有哪些,int占几个字节?byte占几个字节?

1)四种整数类型(byte、short、int、long):    byte:8 位,用于表示最小数据单位,如文件中数据,-128~127    short:16 位,很少用,-32768 ~ 32767    int:32 位、最常用,-2^31-1~2^31  (21 亿)    long:64 位、次常用    注意事项:    int i=5; // 5 叫直接量(或字面量),即 直接写出的常数。    整数字面量默认都为 int 类型,所以在定义的 long 型数据后面加 L或 l。    小于 32 位数的变量,都按 int 结果计算。    强转符比数学运算符优先级高。见常量与变量中的例子。

2)两种浮点数类型(float、double):    float:32 位,后缀 F 或 f,1 位符号位,8 位指数,23 位有效尾数。    double:64 位,最常用,后缀 D 或 d,1 位符号位,11 位指数,52 位有效尾    注意事项:    二 进 制 浮 点 数 : 1010100010=101010001.0*2=10101000.10*2^10(2次方)=1010100.010*2^11(3次方)= . 1010100010*2^1010(10次方)    尾数:  . 1010100010  指数:1010  基数:2    浮点数字面量默认都为 double 类型,所以在定义的 float 型数据后面加F 或 f;double 类型可不写后缀,但在小数计算中一定要写 D 或 X.X    float  的精度没有 long 高,有效位数(尾数)短。    float  的范围大于 long  指数可以很大。    浮点数是不精确的,不能对浮点数进行精确比较。

3)一种字符类型(char):    char:16 位,是整数类型,用单引号括起来的 1 个字符(可以是一个中文字符),使用 Unicode 码代表字符,0~2^16-1(65535) 。    注意事项:    不能为 0个字符。    转义字符:\n  换行  \r  回车  \t Tab 字符  \" 双引号  \\ 表示一个\    两字符 char 中间用“+”连接,内部先把字符转成 int 类型,再进行加法运算,char 本质就是个数!二进制的,显示的时候,经过“处理”显示为字符。

4)一种布尔类型(boolean):true 真  和 false 假。

20.常见的异常类有哪些?处理方式?

NullPointerException:当应用程序试图访问空对象时,则抛出该异常。

SQLException:提供关于数据库访问错误或其他错误信息的异常。

IndexOutOfBoundsException:指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。

NumberFormatException:当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。

FileNotFoundException:当试图打开指定路径名表示的文件失败时,抛出此异常。

IOException:当发生某种I/O异常时,抛出此异常。此类是失败或中断的I/O操作生成的异常的通用类。

ClassCastException:当试图将对象强制转换为不是实例的子类时,抛出该异常。

处理方式

Java异常机制用到的几个关键字:try、catch、finally、throw、throws。

try -- 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。

catch -- 用于捕获异常。catch用来捕获try语句块中发生的异常。

finally -- finally语句块总是会被执行。它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。

throw -- 用于抛出异常。

throws -- 用在方法签名中,用于声明该方法可能抛出的异常。主方法上也可以使用throws抛出。如果在主方法上使用了throws抛出,就表示在主方法里面可以不用强制性进行异常处理,如果出现了异常,就交给JVM进行默认处理,则此时会导致程序中断执行。

21.枚举的了解?

枚举是列出某些有穷序列集的所有成员的程序,一个类里定义几个静态变量,每个变量都是这个类的实例

22. final、 finally、 finalize关键字的区别? volatile关键字的了解?

final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表示该变量是一个常量不能被重新赋值。

finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。

finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调用,当我们调用System的gc()方法的时候,由垃圾回收器调用finalize(),回收垃圾。

volatile关键字的作用:

内存可见性

禁止指令重排

volatile不会让线程阻塞,响应速度比synchronized高

volatile和synchronized的区别(自加)

volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量只有当前线程可以访问该变量,其他线程被阻塞住。

volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的

volatile仅能实现变量的修改可见性不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性

volatile不会造成线程的阻塞synchronized可能会造成线程的阻塞

synchronized和lock的用法区别

synchronized:在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。

lock:需要显示指定起始位置和终止位置。一般使用ReentrantLock类做为锁,多个线程中必须要使用一个ReentrantLock类做为对象才能保证锁的生效。且在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁

23.在一个list中存放的 String类型的字符串,如何实现把其中所有带“王”的字符串从list中去除?

1.遍历集合for(String s:list)

2.判断遍历的对象中是否含有“王”if(s.indexOf(“王”)!=-1)

3.执行删除list.remove(s)

24.string a=“123”;string b=“123”;a+=b;生成了几个对象?

25.如何序列化和反序列化?序列化的目的?

序列化是指将Java对象转换为字节序列的过程,而反序列化则是将字节序列转换为Java对象的过程。

实现序列化:实现Serializable、Externalizable接口

实现反序列化:用ObjectInputStream(对象输入流)类包含一个readObject()方法用来“反序列化”一个对象

目的:

1)Java序列化就是把对象转换成字节序列,而Java反序列化就是把字节序列还原成Java对象。

2)采用Java序列化与反序列化技术,一是实现数据的持久化;二是数据的远程通信




 

猜你喜欢

转载自blog.csdn.net/abu1216/article/details/112298311