java笔试知识点-创新互联

JAVA中四种修饰符的限制范围:
private:修饰的成员只能在同类中别访问,而在同包、子类和其他包中都不能被访问
public:修饰的成员在同类、同包、子类(继承自本类)、其他包都可以访问
protected:修饰的成员在同类、同包、子类中可以访问,其他包中不能被访问
default:修饰的成员在同类、同包中可以访问,但其他包中不管是不是子类都不能被访问

10年积累的成都网站设计、成都做网站经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先建设网站后付款的网站建设流程,更有武胜免费网站建设让你可以放心的选择与我们合作。

final修饰:

final去修饰一个类的时候,表示这个类不能被继承, final类中的成员方法都会被隐式的指定为final方法。

final修饰方法,方法不能被重写。 一个类的private方法会隐式的被指定为final方法。如果父类中有final修饰的方法,那么子类不能去重写。

修饰成员变量

a. 必须初始化值。

b. 被fianl修饰的成员变量赋值,有两种方式:1、直接赋值 2、全部在构造方法中赋初值。

c. 如果修饰的成员变量是基本类型,则表示这个变量的值不能改变。

d. 如果修饰的成员变量是一个引用类型,则是说这个引用的地址的值不能修改,但是这个引用所指向的对象里面的内容还是可以改变的。

注意:final不能和abstract关键字联合使用。

总之,final表示最终的、不可变的。


浅拷贝深拷贝:

数据分为基本数据类型和对象数据类型:

1、基本数据类型的特点:直接存储在栈(stack)中的数据

2、引用数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在堆内存里

引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。

深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的,浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

浅拷贝如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。

Object含有的方法:

Clone:浅拷贝

引申:如何实现深拷贝?:①实现cloneable②先把对象序列化到内存,再反序列化。

class与getClass:

Class:类的Class类实例是通过.class获得的 getClass:是一个对象实例的方法,只有对象实例才有这个方法。

.class功能完全等于.getClass()!只是一个是用类直接获得的,一个是用实例获得的

getName:返回class对象的名称,string字符串

hashcode和equals以及“==”:

两个对象相等,hashcode一定是相等的,两个对象的hashcode相等,这两个对象不一定相等。Hashcode可以重写,如果重写了equals,那么一定要重写hashcode。

基本数据类型,也称原始数据类型byte,short,char,int,long,float,double,boolean。他们之间的比较,应用“==”,比较的是他们的值,引用数据类型用“==”比较的是指向的地址。equals方法,是object中的方法,如果不进行重写的话,比较的也是引用的地址值,实际和“==”一样。 .如果自己所写的类中已经重写了equals方法,那么比较地址指向的内容。

new和newInstance:

newInstance:一般和class.forName搭配使用,class.forName要求jvm去查找加载指定的类,newInstance是给他实例化。

Class.forName("")返回的是类

Class.forName("").newInstance()返回的是object

newInstance( )是一个方法,只能调用无参的构造函数,而且必须保证类已经加载了。

new是一个关键字,生成对象是没有构造函数限制的。

Class.forName和newInstance合起来其实等于new,提供了一种解耦的方式,但是效率低。

例子:

class c = Class.forName("Example");

factory = (ExampleInterface)c.newInstance();

注:java9中已经把newInstance废弃掉了。

wait,notify,notifyAll:

三个方法是Object的本地final方法,无法被重写。

wait()、notify/notifyAll() 必须在synchronized 代码块执行,说明当前线程一定是获取了锁的。

当线程执行wait()方法时候,会释放当前的锁,然后让出CPU,进入等待状态。

当 notify/notifyAll() 被执行时候,会唤醒一个或多个正处于等待状态的线程,然后继续往下执行,直到执行完synchronized 代码块的代码或是中途遇到wait() ,再次释放锁。

也就是说,notify/notifyAll() 的执行只是唤醒沉睡的线程,而不会立即释放锁。

wait() 需要被try catch包围,以便发生异常中断也可以使wait等待的线程唤醒。


String ,StringBuffer,StringBuilder:

String不可变,因为成员变量是final修饰的,Java中String类其实就是对字符数组的封装。String每次变都是重新生成一个string,丢弃之前的。

1、String类可以被继承吗?

String类在声明时使用final关键字修饰,被final关键字修饰的类无法被继承。

单线程操作大量数据可以用stringbuilder,性能高。

多线程要用stringbuffer,其很多方法都加了 synchronized,线程安全。


序列化与反序列化:

序列化就是把对象转换为字节序列的过程,叫对象序列化。

反序列化就是把字节对象恢复为对象的过程。

在代码运行的时候,有些对象的数据信息我们想要持久的保存起来,就把对象变成一连串字节保存文件。

为什么序列化:持久储存数据、网络上传输对象

如何序列化:实现serializable接口,或者Json序列化。

例题: 1、使用Spring框架的好处是什么?

轻量:Spring是轻量的,基本的版本大约2MB

控制反转(IOC):Spring通过控制反转实现类松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们。

面向切面的编程(AOP):Spring支持面向切面的编程,并且把业务逻辑和系统服务分开。

容器:spring包含并管理应用中对象的生命周期和配置。

MVC框架:Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品。

事务管理:Spring提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务。

异常处理:Spring提供方便的API把具体技术相关的异常转换为一致的unchecked异常。

2、Java工厂模式和Spring IOC的区别在哪?

Java工厂是在工厂中修改,在工厂中修改就要重修编译工厂类,重新编译的话就要先停了JVM再重新启动。

Spring IOC是热插拔的,在XML中直接修改,修改xmlspring就会立即发现你改动了XML,会再重新读一遍XML,就会发现新改动了,根本不用重新启动JVM。

3、ORM框架(Object relation mapping)有什么概念?

ORM对象关系映射关系,面向对象的对象模型和关系型数据之间的相互转换。

Hibernate和Mybatis都是常用的ORM框架,两者区别:

(1)mybatis手写SQL,而hibernate提供映射机制,开发人员无需担心。

(2)mybatis控制更细粒度,但可移植型差,hibernate开发DAO很简单,可移植性好。

(3)hibernate拥有完整的日志系统,mybatis则欠缺一些

(4) mybatis相比hibernate需要关心很多细节

(5)sql直接优化上,mybatis要比hibernate方便很多

4、数据库事务的四大特性及事务隔离级别是什么?

(1)事务的四大特性:

原子性(Atomicity):事务包含的所有操作要么全部成功,要么全部失败回滚。

一致性(Consistency):一个事务执行之前和执行之后都必须处于一致性状态。

隔离性(Isolation):当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

持久性(Durability):一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

(2)事务隔离:

更新丢失:两事务同时更新,一个失败回滚覆盖另一个事务的更新。

脏读:事务T1读取到事务T2修改了但是还未提交的数据,之后事务T2又回滚其更新操作,导致事务T1读到的是脏数据。

不可重复读:事务T1读取某个数据后,事务T2对其做了修改,当事务T1再次读该数据时得到与前一次不同的值。

虚读(幻读):事务T1读取在读取某范围数据时,事务T2又插入一条数据,当事务T1再次数据这个范围数据时发现不一样了,出现了一些“幻影行”。

不可重复读和脏读的区别:脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。

幻读和不可重复读的异同:都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。

(3)事务隔离的级别:

读未提交(1000):只限制同一数据写事务禁止其他写事务。解决”更新丢失”。

读已提交(1100):只限制同一数据写事务禁止其它读写事务。解决”脏读”,以及”更新丢失”。

可重复读(1110):限制同一数据写事务禁止其他读写事务,读事务禁止其它写事务(允许读)。解决”不可重复读”,以及”更新丢失”和”脏读”。

串行化(1111):提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。

5、假设有一张用户表,正常的表只能存放大概一千万或是两千万左右的数据,但是有上亿的用户?怎么存储?

横向分割或者纵向分割。

不太严格的将,对于海量数据的数据库,如果是因为表多而数据多,这时候适合垂直切分,即把关系紧密的(比如同一模块)的表切分出来出来放在一个servlet上。如果对于表并不多,但每张表的数据非常多,这时候就适合水平切分,即把表的数据按某种规则切分到对个数据库(server)上。

可以横向分割,把表分割成多个表然后分布式存储。

6、库函数和系统调用是什么?

(1)系统调用是为了方便应用使用操作系统的接口,而库函数是为了方便入门编写应用程序而引出的,比如自己编写一个函数其实也可以说是一个库函数。

(2)系统调用可以理解为内核提供给我们在用户态的接口函数,可以认为是某种内核的库函数。

(3)read()函数是系统调用,而fread()函数是C标准库函数。

7、Java设计模式有哪些?

创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。

结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。

行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

8、讲讲类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,当new的时候,他们的执行顺序。

父类静态成员和静态初始化块 ,按在代码中出现的顺序依次执行

子类静态成员和静态初始化块 ,按在代码中出现的顺序依次执行

结论:对象初始化的顺序,先静态方法,再构造方法,每个又是先基类后子类

父类实例成员和实例初始化块 ,按在代码中出现的顺序依次执行

父类构造方法

子类实例成员和实例初始化块 ,按在代码中出现的顺序依次执行

子类构造方法

9、请你讲述数组和链表数据结构之间各自的时间复杂度。

数组,是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素。但是如果要在数组中增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其中。同样的道理,如果想删除一个元素,同样需要移动大量元素去填掉被移动的元素。如果应用需要快速访问数据,很少插入和删除元素,就应该用数组。

链表 中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起,每个结点包括两个部分:一个是存储 数据元素 的 数据域,另一个是存储下一个结点地址的 指针。

如果要访问链表中一个元素,需要从第一个元素开始,一直找到需要的元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了,只要修改元素中的指针就可以了。如果应用需要经常插入和删除元素你就需要用链表。

内存存储区别

数组从栈中分配空间, 对于程序员方便快速,但自由度小。

链表从堆中分配空间, 自由度大但申请管理比较麻烦。

逻辑结构区别

数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。

链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项)

总结

存取方式上,数组可以顺序存取或者随机存取,而链表只能顺序存取;

存储位置上,数组逻辑上相邻的元素在物理存储位置上也相邻,而链表不一定;

存储空间上,链表由于带有指针域,存储密度不如数组大;

按序号查找时,数组可以随机访问,时间复杂度为O(1),而链表不支持随机访问,平均需要O(n);

按值查找时,若数组无序,数组和链表时间复杂度均为O(1),但是当数组有序时,可以采用折半查找将时间复杂度降为O(logn);

插入和删除时,数组平均需要移动n/2个元素,而链表只需修改指针即可;

空间分配方面:

数组在静态存储分配情形下,存储元素数量受限制,动态存储分配情形下,虽然存储空间可以扩充,但需要移动大量元素,导致操作效率降低,而且如果内存中没有更大块连续存储空间将导致分配失败;

链表存储的节点空间只在需要的时候申请分配,只要内存中有空间就可以分配,操作比较灵活高效;

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网站栏目:java笔试知识点-创新互联
文章路径:http://pwwzsj.com/article/dgdchh.html