1.字符串+数字

System.out.println(1+"10"+3+"2");//11032
System.out.println(1+2+"10"+3+"2");//31032
System.out.println(1+"10"+3+1+"2");//110312
在遇到string类型之前,int间使用“+”还是表示数值的相加,但是遇到第一个string后,后面就都是按string类型来了,变成字符串的拼接

1.applet 的方法

Applet 类是浏览器类库中最为重要的类,同时也是所有 JAVA 小应用程序的基本类。 一个 Applet 应用程序从开始运行到结束时所经历的过程被称为 Applet 的生命周期。 Applet 的生命周期涉及 init()  start()  stop()  destroy() 四种方法,这 4 种方法都是 Applet 类的成员,可以继承这些方法,也可以重写这些方法,覆盖原来定义的这些方法。除此之外,为了在 Applet 程序中实现输出功能,每个 Applet 程序中还需要重载 paint() 方法:

1、  public void init()

init()方法是 Applet 运行的起点。当启动 Applet 程序时,系统首先调用此方法,以执行初始化任务。

2、  public void start()

start()方法是表明 Applet 程序开始执行的方法。当含有此 Applet 程序的 Web 页被再次访问时调用此方法。因此,如果每次访问 Web 页都需要执行一些操作的话,就需要在 Applet 程序中重载该方法。在 Applet 程序中,系统总是先调用 init() 方法,后调用 start() 方法。

3、  public void stop()

stop()方法使 Applet 停止执行,当含有该 Applet 的 Web 页被其他页代替时也要调用该方法。

4、  public void destroy()

destroy()方法收回 Applet 程序的所有资源,即释放已分配给它的所有资源。在 Applet 程序中,系统总是先调用 stop() 方法,后调用 destroy() 方法。

5、  paint(Graphics g)

paint(Graphics g)方法可以使 Applet 程序在屏幕上显示某些信息,如文字、色彩、背景或图像等。参数 g 是 Graphics 类的一个对象实例,实际上可以把 g 理解为一个画笔。对象 g 中包含了许多绘制方法,如 drawstring() 方法就是输出字符串。


1.Java值传递

指出下列程序运行的结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
publicclassExample{
    String str=newString("tarena");
    char[]ch={'a','b','c'};
    publicstaticvoidmain(String args[]){
        Example ex=newExample();
        ex.change(ex.str,ex.ch);
        System.out.print(ex.str+" and ");
        System.out.print(ex.ch);
    }
    publicvoidchange(String str,charch[]){
   //引用类型变量,传递的是地址,属于引用传递。
        str="test ok";
        ch[0]='g';
    }
}

正确答案: B   你的答案: D (错误)

tarena and abc
tarena and gbc
test ok and abc
test ok and gbc

string和char数组都是引用类型,引用类型是传地址的,会影响原变量的值,但是string是特殊引用类型,为什么呢?因为string类型的值是不可变的,为了考虑一些内存,安全等综合原因,把它设置成不可变的; 不可变是怎么实现的?Java在内存中专门为string开辟了一个字符串常量池,用来锁定数据不被篡改,所以题目中函数中的str变量和原来的str已经不是一个东西了,它是一个局部引用,指向一个testok的字符串,随着函数结束,它也就什么都没了,但是char数组是会改变原值的

1.java多线程

下列代码编译和运行的结果是:()                                             
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Threads4{
 public staticvoid main(String[] args){
 new Threads4().go();
 }
 public void go(){
 Runnable r=new Runnable(){
 public void run(){
 System.out.print("foo");
 }
 };
 Thread t=new Thread(r);
 t.start();
 }
 }

实现多线程的方式有两种
①extends Thread   
从Java.lang.Thread类派生一个新的线程类,重写它的run()方法
 ②implements Runnable。
实现Runnable接口,重写Runnable接口中的run()方法

这两种情况是我们最常见的,还有一种是由第二种变形而来的直接new Runnable(){},我们都知道java的接口是不可以实例化的,但代码中的new Runnable(){xxx}确是实例化了,为什么? 接口和抽象类不可以实例化是对的,这个是java语法规范来的,**而new Runnable(){}其实不是实例化Runnable接口来的,实际上一种内部类的一种简写** 
①首先构造了一个”implements Runnable “的无名local内部类(方法内的内部类)
②然后构造了这个无名local内部类的一个实例
③然后用Runnable来表示这个无名local内部类的type(OO多态)。 例如上面这段代码编译后你会看到其实是编译了两个类来的,如下: 
其中Text2$1就是无名local内部内类,这个也就很好地解释了为什么在main()方法中new Runnable(){xxx}里面的调用main()方法中的变量的时候要用final关键字来修饰

两种方法的区别:
    1.start方法
         用 start方法来启动线程,是真正实现了多线程, 通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法。但要注意的是,此时无需等待run()方法执行完毕,即可继续执行下面的代码。所以run()方法并没有实现多线程
    2.run方法
         run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码。


下面程序的运行结果:()
1
2
3
4
5
6
7
8
9
10
11
12
13
publicstaticvoidmain(String args[]) {
        Thread t=newThread(){
        publicvoid run(){
            dianping();
             
        }
    };
    t.run();
    System.out.print("dazhong");
    }
    staticvoiddianping(){
        System.out.print("dianping");
}

正确答案: B   你的答案: C (错误)

dazhongdianping
dianpingdazhong
a和b都有可能
dianping循环输出,dazhong夹杂在中间
如果调用run() 选b
如果调用start() 选c
因为调用start后并不保证线程启动的顺序
在上面main()方法中,并没有创建一个新的线程,只是简单地方法调用而已,如果想要创建线程,需要t.start();创建线程,等待cpu时间片,而run()方法只是简单地方法调用,所以先执行run(),在输出dazhong


1.分配在内存哪个区域?

用new创建的对象在堆区
函数中的临时变量在栈去
java中的字符串在字符串常量区

2.weblogic中开发消息Bean时的persistent与non-persisten的差别:

  • persistent方式的MDB可以保证消息传递的可靠性,也就是如果EJB容器出现问题而JMS服务器依然会将消息在此MDB可用的时候发送过来。
  • non-persistent方式的消息将被丢弃

在Web应用程序中,(    )负责将HTTP请求转换为HttpServletRequest对象

Apache就是一个Http服务器,Tomcat是一个web容器,静态的htmlApache还可以处理,但是动态的需要转发给Tomcat去处理了,比如jsp页面,请求先经由Apache转发给Tomcat再由Tomcat解析请求。所以应该是web容器去解析成request对象。

web容器是一种服务程序,在服务器一个端口就有一个提供相应服务的程序,而这个程序就是处理从客户端发出的请求,如JAVA中的Tomcat容器,ASP的IIS或PWS都是这样的容器。一个服务器可以多个容器。


下面哪项技术可以用在WEB开发中实现会话跟踪实现?

正确答案: A B C D   你的答案: A B (错误)

session
Cookie
地址重写
隐藏域
有四种方法可以实现会话跟踪技术:URL重写、隐藏表单域、Cookie、Session。
1).隐藏表单域:<input type="hidden">,非常适合步需要大量数据存储的会话应用。
2).URL 重写:URL 可以在后面附加参数,和服务器的请求一起发送,这些参数为名字/值对。
3).Cookie:一个 Cookie 是一个小的,已命名数据元素。服务器使用 SET-Cookie 头标将它作为 HTTP
响应的一部分传送到客户端,客户端被请求保存 Cookie 值,在对同一服务器的后续请求使用一个
Cookie 头标将之返回到服务器。与其它技术比较,Cookie 的一个优点是在浏览器会话结束后,甚至
在客户端计算机重启后它仍可以保留其值
4).Session:使用 setAttribute(String str,Object obj)方法将对象捆绑到一个会话

3.关于Java声明

B:   java的访问权限有public、protected、private和default的,但是default不能修饰变量
C:普通变量不能用abstract修饰,abstract一般修饰方法和类
D:被定义为abstract的类需要被子类继承,但是被修饰为final的类是不能被继承和改写的

4.包装类与数据类型,以及转换

1、整数类型byte(1个字节)short(2个字节)int(4个字节)long(8个字节)

2、字符类型char(2个字节)

3、浮点类型float(4个字节)double(8个字节)

C,默认的浮点数据类型是double,如果要指明使用float,则需要在后面加f
D,基本数据类型是没有静态方法的,但是基本数据类型的包装类却有




通俗的讲,就是基本数据类型和包装类之间的转换。如: int  类型和  Integer  类的转换
基本数据类型转化成包装类是装箱  (如: int  -->  Integer)。
包装类转化成基本数据类型就是拆箱  (如:Integer  -->  int)。
包装类就是引用类型,基本数据类型就是值类型。所以选C 装箱、拆箱操作发生在:
引用类型与值类型之间


假定x和y为double型,则表达式x=2,y=x+3/2的值是

正确答案: D   你的答案: A (错误)

3.500000
3
2.000000
3.000000
按照优先级,先做除运算,再考虑数值类型的转换。。
double是双精度浮点数,所以x是2.000000,加上3/2由于除号两边都是整形,所以3/2=1,y为double型,所以y为3.000000。

’a’ = 1/3
‘a’是char类型,1/3是int类型。将int赋值给char属于从高向低赋值,则错误


5.如何获取ServletContext设置的参数值

getParameter()是获取POST/GET传递的参数值;
getInitParameter获取Tomcat的server.xml中设置Context的初始化参数
getAttribute()是获取对象容器中的数据值;
getRequestDispatcher是请求转发。

servlet在多线程下其本身并不是线程安全的。在Servlet类中可能会定义共享的类变量
如果在类中定义成员变量,而在service中根据不同的线程对该成员变量进行更改,那么在并发的时候就会引起错误。最好是在方法中,定义局部变量,而不是类变量或者对象的成员变量。由于方法中的局部变量是在栈中,彼此各自都拥有独立的运行空间而不会互相干扰,因此才做到线程安全。

init()方法是servlet生命的起点。一旦加载了某个servlet,服务器将立即调用它的init()方法
service()方法处理客户机发出的所有请求
destroy()方法标志servlet生命周期的结束
init方法: 是在servlet实例创建时调用的方法,用于创建或打开任何与servlet相的资源和初始 化servlet的状态,Servlet规范保证调用init方法前不会处理任何请求 
 service方法:是servlet真正处理客户端传过来的请求的方法,由web容器调用, 根据HTTP请求方法(GET、POST等),将请求分发到doGet、doPost等方法 
destory方法:是在servlet实例被销毁时由web容器调用。Servlet规范确保在destroy方法调用之 前所有请求的处理均完成,需要覆盖destroy方法的情况:释放任何在init方法中 打开的与servlet相关的资源存储servlet的状态

6.3个访问权限

protected方法,则只能在子类以及基类中调用该方法,其他的非继承基类的类,是不能有访问权限的;
子类继承父类,并重写父类的protected成员方法,该方法的可见性可以修改,这是对的,因为子类继承父类的方法,访问权限可以相同或往大了改   

private是私有变量,只能用于当前类中,题目中的main方法也位于当前类,所以可以正确输出



6.Java输入输出

下面哪种流可以用于字符输入:

正确答案: C   你的答案: A (错误)

java.io.inputStream
java.io.outputStream
java.io.inputStreamReader
java.io.outputStreamReader
首先B和D排除,题目是要求输入。
A和C之间,inputStream是字节流输入流;而inputStreamReader是对字符流的处理,inputStreamReader将字符流处理成字节流,题目要求是用于处理字符输入,所以选C。


Java创建对象的说法正确的有()

正确答案: A B C D   你的答案: A B C D (正确)

用new语句创建对象,是最常见的创建对象的方法。
运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。
调用对象的clone()方法。
运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。


6.Java常识

java源文件的后缀名是.java。源文件通过jvm虚拟机编译后会生成二进制字节码文件,后缀是.class
Java   提供的事件处理模型是一种人机交互模型。它有三个基本要素:

1) 事件源(Event Source):即事件发生的场所,就是指各个组件,如按钮等,点击按钮其实就是组件上发生的一个事件;

2) 事件(Event):事件封装了组件上发生的事情,比如按钮单击、按钮松开等等;

3) 事件***(Event Listener):负责监听事件源上发生的特定类型的事件,当事件到来时还必须负责处理相应的事件;

面向对象的语言里没有“过程”
面向过程的语言里没有“对象”

AOP和OOP都是一套方法论,也可以说成设计模式、思维方式、理论规则等等。
AOP不能替代OOP,OOP是obejct abstraction,而AOP是concern abstraction,前者主要是对对象的抽象,诸如抽象出某类业务对象的公用接口、报表业务对象的逻辑封装,更注重于某些共同对象共有行为的抽象,如报表模块中专门需要报表业务逻辑的封装,其他模块中需要其他的逻辑抽象 ,而AOP则是对分散在各个模块中的共同行为的抽象,即关注点抽象。一些系统级的问题或者思考起来总与业务无关又多处存在的功能,可使用AOP,如异常信息处理机制统一将自定义的异常信息写入响应流进而到前台展示、行为日志记录用户操作过的方法等,这些东西用OOP来做,就是一个良好的接口、各处调用,但有时候会发现太多模块调用的逻辑大都一致、并且与核心业务无大关系,可以独立开来,让处理核心业务的人专注于核心业务的处理,关注分离了,自然代码更独立、更易调试分析、更具好维护。
核心业务还是要OOP来发挥作用,与AOP的侧重点不一样,前者有种纵向抽象的感觉,后者则是横向抽象的感觉, AOP只是OOP的补充,无替代关系。

动态类型语言是指在运行期间才去做数据类型检查的语言,也就是说,在用动态类型的语言编程时,永远也不用给任何变量指定数据类型,该语言会在你第一次赋值给变量时,在内部将数据类型记录下来。静态类型语言与动态类型语言刚好相反,它的数据类型是在编译其间检查的,也就是说在写程序时要声明所有变量的数据类型,C/C++是静态类型语言的典型代表,其他的静态类型语言还有C#、JAVA等。

以java8为准,switch支持10种类型
基本类型:byte char short int
对于包装类 :Byte,Short,Character,Integer String enum
2、实际只支持int类型 Java实际只能支持int类型的switch语句,那其他的类型时如何支持的
a、基本类型byte char short 原因:这些基本数字类型可自动向上转为int, 实际还是用的int。
b、基本类型包装类Byte,Short,Character,Integer 原因:java的自动拆箱机制 可看这些对象自动转为基本类型
c、String 类型 原因:实际switch比较的string.hashCode值,它是一个int类型 如何实现的,网上例子很多。此处不表。
d、enum类型 原因 :实际比较的是enum的ordinal值(表示枚举值的顺序),它也是一个int类型 所以也可以说 switch语句只支持int类型

length 返回当前长度
如果字符串长度没有初始化长度大,capacity返回初始化的长度
如果append后的字符串长度超过初始化长度,capacity返回增长后的长度

对属性使用getter和setter方法,体现的是注入性

数组命名时名称与[]可以随意排列,但声明的二维数组中第一个中括号中必须要有值,它代表的是在该二维数组中有多少个一维数组。


每个类都使用Object类作为超类,而final修饰的类不能被继承
C.
即string是final修饰的
D.Class类中的forName()方法返回与带有给定字符串名的类或接口相关联的Class对象(装载其他类)

顶层容器是指可以不能被其他容器包含 ,是容纳其他容器的容器组件,
顶层容器包含JApplet、JDialog、JFrame和JWindow及其子类.
JFrame中就可以放Jtree(树形组件)


较典型的面向对象语言有:

simula 67,支持单继承和一定含义的多态和部分动态绑定
Smalltalk支持单继承、多态和动态绑定;
EIFFEL,支持多继承、多态和动态绑定;
C++,支持多继承、多态和部分动态绑定。
Java,支持单继承、多态和部分动态绑定。
五种语言涉及概念的含义虽然基本相同,但所用术语有别。
C#,也支持单继承,与Java和C++等有很多类似之处……

复制效率

看了几个评论,你们会就好好回答,不会就别复制别人错误答案耽误别人好吧? 
复制的效率System.arraycopy>clone>Arrays.copyOf>for循环循环逐一复制,这个有兴趣自己测试一下就知道了。
这里面在System类源码中给出了arraycopy的方法,是native方法,也就是本地方法,肯定是最快的。而Arrays.copyOf(注意是Arrays类,不是Array)的实现,在源码中是调用System.copyOf的,多了一个步骤,肯定就不是最快的。前面几个说System.copyOf的不要看,System类底层根本没有这个方法,自己看看源码就全知道了。


优化Hibernate所鼓励的7大措施:

1.尽量使用many-to-one,避免使用单项one-to-many
2.灵活使用单向one-to-many
3.不用一对一,使用多对一代替一对一
4.配置对象缓存,不使用集合缓存
5.一对多使用Bag 多对一使用Set
6.继承使用显示多态 HQL:from object polymorphism="exlicit" 避免查处所有对象
7.消除大表,使用二级缓存



下列关于包(package)的描述,正确的是()

正确答案: D   你的答案: A (错误)

包(package)是Java中描述操作系统对多个源代码文件组织的一种方式。
import语句将所对应的Java源文件拷贝到此处执行。
包(package)是Eclipse组织Java项目特有的一种方式。
定义在同一个包(package)内的类可以不经过import而直接相互使用。
1、为了更好地组织类,Java提供了包机制。包是类的容器,用于分隔类名空间。如果没有指定包名,所有的示例都属于一个默认的无名包。Java中的包一般均包含相关的类,java是跨平台的,所以java中的包和操作系统没有任何关系,java的包是用来组织文件的一种虚拟文件系统。A错
2、import语句并没有将对应的java源文件拷贝到此处仅仅是引入,告诉编译器有使用外部文件,编译的时候要去读取这个外部文件。B错
3、Java提供的包机制与IDE没有关系。C错
4、定义在同一个包(package)内的类可以不经过import而直接相互使用。

解释性,编译性

下面关于程序编译说法正确的是()

正确答案: C   你的答案: D (错误)

java语言是编译型语言,会把java程序编译成二进制机器指令直接运行
java编译出来的目标文件与具体操作系统有关
java在运行时才进行翻译指令
java编译出来的目标文件,可以运行在任意jvm上

A:.java编译成的是字节码,再被各系统的jvm翻译成本系统可以识别的机器码,这就是java一次编程多平台应用的跨平台性 
B:java源文件生成的是class文件,与系统无关 
C:注意字节码和机器码不是一回事 java程序在运行时字节码才会被jvm翻译成机 器码,所以说java是解释性语言 
D:注意jvm的版本,好比人穿裤子,一条裤子能被任何人穿上吗

编译型语言的首先将源代码编译生成机器语言,再由机器运行机器码二进制)。像C/C++等都是编译型语言。程序执行效率高,依赖编译器,跨平台性差些。如C、C++、Delphi等
解释性语言在运行程序的时候才翻译,比如解释性basic语言,专门有一个解释器能够直接执行basic程序,每个语句都是执行的时候才翻译。这样解释性语言每执行一次就要翻译一次,效率比较低。如JavaScript、VBScript、Perl、Python、Ruby、MATLAB 等等
Java不同于一般的编译语言和直译语言。它首先将源代码编译成字节码,然后依赖各种不同平台上的虚拟机来解释执行字节码,从而实现了“一次编写到处运行”的跨平台特性, 所以说java是一种解释型的语言



JDK提供的用于并发编程的同步器有哪些?

正确答案: A B C   你的答案: B C (错误)

Semaphore
CyclicBarrier
CountDownLatch
Counter

答案:ABC
A,Java 并发库 的Semaphore 可以很轻松完成信号量控制,Semaphore可以控制某个资源可被同时访问的个数,通过 acquire() 获取一个许可,如果没有就等待,而 release() 释放一个许可。
B,CyclicBarrier 主要的方法就是一个:await()。await() 方法没被调用一次,计数便会减少1,并阻塞住当前线程。当计数减至0时,阻塞解除,所有在此 CyclicBarrier 上面阻塞的线程开始运行。
C,直译过来就是倒计数(CountDown)门闩(Latch)。倒计数不用说,门闩的意思顾名思义就是阻止前进。在这里就是指 CountDownLatch.await() 方法在倒计数为0之前会阻塞当前线程。
D,Counter不是并发编程的同步器


6.JSP

JSP分页代码中,哪个步骤次序是正确的?

正确答案: A   你的答案: B (错误)

先取总记录数,得到总页数,最后显示本页的数据。
先取所有的记录,得到总页数,再取总记录数,最后显示本页的数据。
先取总页数,得到总记录数,再取所有的记录,最后显示本页的数据。
先取本页的数据,得到总页数,再取总记录数,最后显示所有的记录。

在 myjsp.jsp 中,关于下面的代码说法错误的是: (  )   
<%@ page language="java" import="java.util.*" errorPage="error.jsp" isErrorPage="false" %> 

正确答案: A   你的答案: D (错误)

该页面可以使用 exception 对象
该页面发生异常会转向 error.jsp
存在 errorPage 属性时,isErrorPage 是默认为 false
error.jsp 页面一定要有isErrorPage 属性且值为 true

当isErrorPage ="false"时,用errorPage="error.jsp"(isErrorPage默认是false)
当isErrorPage ="true"时,页面会直接使用exception
exception是JSP九大内置对象之一,其实例代表其他页面的异常和错误。只有当页面是错误处理页面时,即isErroePage为 true时,该对象才可以使用。

errorPage 的意思是设置当前页面要引入错误的页面。也就是浮面当前页面如果出现错误就会跳转到errorPage所指定的页面。 
isErrorpage 的意思是当前页面为错误页面
isErrorPage默认值为false,若要当前页面为错误页面就设置isErrorPage=true。

6.原码,补码,反码

由3 个“1”和 5 个“0”组成的 8 位二进制补码,能表示的最小整数()

正确答案: B   你的答案: B (正确)

-126
-125
-32
-3
既然求最小整数,那肯定先想到负数,则最高位(符号位)一定为1,原码中肯定是1所在的位数越高,值越小,而补码是由原码取反加1得到的,则在补码中1所在的位数一定要越低,即补码为1000 0011;由补码求得原码:1111 1101=-(64+32+16+8+4+1)=-125;

基本概念: 
1.正数的原码、反码、补码都相同; 
2.负数的原码:最高位为1,其余位为真值的绝对值; 
3.负数的反码:在原码的基础上,符号位不变,其余位按位取反; 
4.负数的补码:在原码的基础上,符号位不变,其余位取反,最后加1;也就是在反码的基础上加1。 
负数的补码向源码转换步骤
 1. -12的补码:1111 0100 
2. 最高位不变,其余位取反:1000 1011 
3. 加一得到原码:1000 1100 
思路分析: 1. 求最小的值,那么肯定是负数最小,最高位为1表示为负数 
2. 剩下的5个0和2个1要组成一个补码,只有1000 0011这种补码形式转换成原码后值最大 
操作步骤 1. 最高位不变,其余位去反 1111 1100 
2.加1 1111 1101 计算后得到-(64+32+16+8+4+1)=-125


7.Java内部类

对于局部内部类,只有在方法的局部变量被标记为final或局部变量是effctively final的,内部类才能使用它们
成员内部类位于外部类内部,可以直接调用外部类的所有方法(静态方法和非静态方法)

匿名内部类用法与局部内部类不一致,首先从定义上就不一样,匿名类用在任何允许存在表达式的地方,而局部内部类用于在任何允许出现局部变量的地方出现。
还有更重要的是匿名类只能使用一次,而局部类则可以在自己的定义域内多次使用。
静态内部类不能直接访问外部类的非静态成员,但可以通过new外部类().成员的方式访问。
可以被abstract,final修饰,不能被public,private修饰



8. java threadlocal

ThreadLocal存放的值是线程封闭,线程间互斥的,主要用于线程内共享一些数据,避免通过参数来传递
从线程的角度看,每个线程都保持一个对其线程局部变量副本的隐式引用,只要线程是活动的并且 ThreadLocal 实例是可访问的;在线程消失之后,其线程局部实例的所有副本都会被垃圾回收
在Thread类中有一个Map,用于存储每一个线程的变量的副本
对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式
ThreadLocal类用于创建一个线程本地变量
在Thread中有一个成员变量ThreadLocals,该变量的类型是ThreadLocalMap,也就是一个Map,它的键是threadLocal,值为就是变量的副本。通过ThreadLocal的get()方法可以获取该线程变量的本地副本,在get方法之前要先set,否则就要重写initialValue()方法。
ThreadLocal的使用场景:
数据库连接:在多线程中,如果使用懒汉式的单例模式创建Connection对象,由于该对象是共享的,那么必须要使用同步方法保证线程安全,这样当一个线程在连接数据库时,那么另外一个线程只能等待。这样就造成性能降低。如果改为哪里要连接数据库就来进行连接,那么就会频繁的对数据库进行连接,性能还是不高。这时使用ThreadLocal就可以既可以保证线程安全又可以让性能不会太低。但是ThreadLocal的缺点时占用了较多的空间。

9.关于对象序列化描述

使用ObjectOutputStream和ObjectInputStream可以将对象进行传输.
声明为static和transient类型的成员数据不能被串行化。因为static代表类的状态, transient代表对象的临时数据。

对象序列化的所属类需要实现Serializable接口

10.下面有关java的instanceof、?、&、&&说法正确

instanceof 可用来判断某个实例变量是否属于某种类的类型。
但是实例变量可以放置在前面也可以放置在后面,还可以判断某个类是否属于某个类的子类的类型
"?:"  三目运算符
&在逻辑运算中是非短路逻辑与,在位运算中是按位与
&& 逻辑运算:逻辑与
&&是逻辑与 即判断&&两侧的表达式是否都为真,都为真则此&&表达式值为真;& 是按位与 即将&两侧的数用二进制展开,每一位都求与运算,最后得到的二进制数即为结果;逻辑与结果只讲真和假,而按位与得出的却是实实在在的一个数

10. Java继承


在一个子类被创建的时候,首先会在内存中创建一个父类对象,然后在父类对象外部放上子类独有的属性,两者合起来形成一个子类的对象。所以所谓的继承使子类拥有父类所有的属性和方法其实可以这样理解,子类对象确实拥有父类对象中所有的属性和方法,但是父类对象中的私有属性和方法,子类是无法访问到的,只是拥有,但不能使用。就像有些东西你可能拥有,但是你并不能使用。所以子类对象是绝对大于父类对象的,所谓的子类对象只能继承父类非私有的属性及方法的说法是错误的。可以继承,只是无法访问到而已。
子类能继承父类的所有成员

class Car extends Vehicle
{
    public static void main (String[] args)
    {
        new  Car(). run();
    }
    private final void run()
    {
        System. out. println ("Car");
    }
}
class Vehicle
{
    private final void run()
    {
        System. out. println("Vehicle");
    }
}
运行结果为  car

首先final声明的方法是不能被覆盖的,但是这里并不错误,因为方法是private的,也就是子类没有继承父类的run方法,因此子类的run方法跟父类的run方法无关,并不是覆盖。new Car().run()也是调用子类的run方法。
扩展:如果父类方法将private改为public 会怎样?
        会报错,因为父类方法有final修饰,不能被覆盖。
会报编译的错误,报错位置在子类方法的声明的位置,改成public的错误信息是覆盖后的方法的访问权限小于父类的错误


final不能被子类覆盖,但是基类的private方法,只有非private方法才能被覆盖。子类虽然继承了基类的所有内容,但是private和构造器等对子类是不可见的,不能直接访问,但是可以调用基类的非parivate方法从而访问基类的private方法,也会引起很多问题。
class Shape {  
    private Shape wf;  
    protected Shape() {  
        wf = this;  
    }  
    private int length() {  
        return 0;  
    }  
    private int width() {  
        return 0;  
    }  
    public int getArea() {  
        return wf.length()*wf.width();  
    }  
}  
public class OverridingShape extends Shape {  
    public int length() {  
        return 10;  
    }  
    //@Override 不是覆盖,基类该方法是private,子类不可见
    public int width() {  
        return 10;  
    }   
    public static void main(String[] args) {  
        Shape s=new OverridingShape();  
        System.out.println(s.getArea());  
//结果是0而不是100 调用的是父类的方法,然后访问的是父类的private方法
    }  
}  




11.左增和右增



包装类的值都是final 不可变的,对于++b 或者b++ ,只是新创建了一个对象,然后把引用传给了原对象句柄,在函数中操作,只是形参的临时句柄改变了指向,实参的句柄还是指向原来的对象。所以即使不是b = b++ 这种,b的值在add之后也是不会变的。 Byte类型值大小为-128~127之间

java中只有byte, boolean是一个字节, char是两个字节, 所以对于java来说127不会发生溢出, 输出328
但是对于c/c++语言来说, char是一个字节, 会发生溢出, 对127加一发生溢出,  0111 1111 --> 1000 0000, 1000 0000为补码-128, 所以结果为200-128=72


12.成员变量和局部变量的区别


1、成员变量是独立于方法外的变量,局部变量是类的方法中的变量
1)、成员变量:包括实例变量类变量,用static修饰的是类变量,不用static修饰的是实例变量

this关键字

区分成员变量和局部变量的重名问题,this.name指的是类中的成员变量--而不是方法内部的


2)、局部变量:包括形参,方法局部变量,代码块局部变量,存在于方法的参数列表和方法定义中以及代码块中。
2、成员变量可以被public,protect,private,static等修饰符修饰,而局部变量不能被控制修饰符及 static修饰;两者都可以定义成final型。
3、成员变量存储在堆,局部变量存储在栈。局部变量的作用域仅限于定义它的方法,在该方法的外部无法访问它。成员变量的作用域在整个类内部都是可见的,所有成员方法都可以使用它。如果访问权限允许,还可以在类的外部使用成员变量。
4、局部变量的生存周期与方法的执行期相同。当方法执行到定义局部变量的语句时,局部变量被创建;执行到它所在的作用域的最后一条语句时,局部变量被销毁。类的成员变量,如果是实例成员变量,它和对象的生存期相同。而静态成员变量的生存期是整个程序运行期。
5、成员变量在累加载或实例被创建时,系统自动分配内存空间,并在分配空间后自动为成员变量指定初始化值,初始化值为默认值,基本类型的默认值为0,复合类型的默认值为null。(被final修饰且没有static的必须显式赋值),局部变量在定义后必须经过显式初始化后才能使用,系统不会为局部变量执行初始化。
6、局部变量可以和成员变量 同名,且在使用时,局部变量具有更高的优先级,直接使用同名访问,访问的是局部变量,如需要访问成员变量可以用this.变量名访问
本例中i为成员变量,有默认的初始值为0,如果定义在方法内部,就没有初始值
类变量在不设置初始值时,会进行默认值赋值,而局部方法中声明的变量则必须进行初始化,他不会进行默认值赋值。

13.Java多态

class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
public void bark(){
System.out.println("狗可以吠叫");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal();
Animal b = new Dog();
a.move();
b.move();
b.bark();
}
}
编译错误:The method bark() is undefined for the type Animal。Animal中没有定义bark()方法。
Dog继承自Animal。
当用Dog对象初始化Animal类对象时,完成了对Animal对象中方法与变量的覆盖与隐藏,也就是b.move()调用的是Dog中move()方法。而Animal中本身并没有bark()方法,不存在被覆盖的情况,亦无法访问,也就是b.bark()会报错。
编译看左边,运行看右边。 父类型引用指向子类型对象,无法调用只在子类型里定义的方法

结合
在调用成员变量以及静态方法时,“编译看左边,运行看左边”,即程序编译时创建了一个Animal类型的对象,并且使用new Cat()对于这个Animal对象赋值,但最终得到的还是一个Animal类的对象,只需要看“=”左边的Animal animal即可。

但是要调用非静态方法时,由于Animal类的对象是用Cat()来实例化的,这个非静态方法在运行时会被重写,从而输出子类中方法重写后的结果。这就是“编译看左边,运行看右边”。

14.关于类变量调用和静态变量

已知如下类说明:

1
2
3
4
5
6
7
8
publicclassTest{
private float f=1.0f;
intm=12;
static int n=1;
public static void main(String args[]){
Test t=newTest();
}
}
t.f = 1.0
this.n
Test.m
Test.n

A:编译不成功,因为float浮点类型默认是double类型 所以float f=1.0f;(必须加上f 强调定义的是float)此处是精度由高(double)向低(float)转型所以会报错   但是若是float f=1;这里是默认类型是Int 类型  精度由低(int)向高转型(float)不丢失精度不会报错。
B:this的使用时针对在方法内部使局部变量等值于实例变量而使用的一个关键字,此处的n是静态变量而非实例变量 所以this的调用会出错(试想一下,static本来是全类中可以使用的,是全局的,你非得this去调用,这不是区分局部变量和实例变量的分水线吗?但是此处是全局的,不需要区分)在static的main方法里用有问题, 如果是普通的方法里this.n没问题静态方法不能以任何方式引用thissuper关键字。
C:m是实例变量,什么是实例变量:就是需要new 一个对象出来才能使用的,这里直接用类名就调用了,jvm怎么知道m是谁?
D:类变量可以通过类直接调用

静态方法中不能调用非静态属性,可以调用非静态方法(通过创建一个实例);方法中可以调用全局静态属性(全局静态变量),通过  实例.变量名  或是  类名.变量名  两种皆可。



在java中,无论在何处调用,使用静态属性必须以类名做前缀。---错误
1.如果是本类使用,可以直接就用静态变量名。
2如果是其他类使用,可以使用类名来调用,也可以创建一个实例对象来调用。
3如果静态变量所在的类是静态类,那么不管在本类里或者在其他外部类,都可以直接使用静态变量名。


被static修饰的变量称为静态变量,静态变量属于整个类,而局部变量属于方法,只在该方法内有效,所以static不能修饰局部变量



阅读如下代码。 请问,对语句行 test.hello(). 描述正确的有()

1
2
3
4
5
6
7
8
9
10
11
12
13
packageNowCoder;
classTest {
    publicstaticvoidhello() {
        System.out.println("hello");
    }
}
publicclassMyApplication {
    publicstaticvoidmain(String[] args) {
        // TODO Auto-generated method stub
        Test test=null;
        test.hello();
    }
}

正确答案: A   你的答案: B (错误)

能编译通过,并正确运行
因为使用了未初始化的变量,所以不能编译通过
以错误的方式访问了静态方法
能编译通过,但因变量为null,不能正常运行

因为Test类的hello方法是静态的,所以是属于类的,当实例化该类的时候,静态会被优先加载而且只加载一次,所以不受实例化new Test();影响,只要是使用到了Test类,都会加载静态hello方法!
另外,在其他类的静态方法中也是可以调用公开的静态方法,此题hello方法是使用public修饰的所以在MyApplication中调用hello也是可以的。
总结:即使Test test=null;这里也会加载静态方法,所以test数据中包含Test类的初始化数据。(静态的,构造的,成员属性)
        因此test.hello是会调用到hello方法的。

很简单,静态方法属于静态绑定,编译器根据引用类型所属的静态类型为它绑定其对应的方法。此语句会翻译成invokestatic,该指令的调用中不会涉及this,所以不会依赖对象! 还有引用类型=null,其实就是指该引用在堆中没有对应的对象,但是编译的时候还是能根据声明找到其所属的静态类型。



15.Python 中万物皆为对象

  • 函数可以赋值给一个变量
  • 函数可以作为元素添加到集合对象中
  • 函数可以作为参数值传递给其它函数
  • 函数可以当做函数的返回值

16.python socket操作

  • 使用recvfrom()接收TCP数据   错误              udp! socket.recv是tcp协议,recvfrom是udp传输 返回值是(data,address)
    其中data是包含接收数据的字符串,address是 发送数据 的套接字地址。
  • 使用getsockname()获取连接套接字的远程地址     错误    自己的! 返回套接字自己的地址 
    通常是一个元组(ipaddr,port)
  • 使用connect()初始化TCP服务器连接 连接到address处的套接字。正确
    一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
  • 服务端使用listen()开始TCP监听 正确
    

17.Python赋值深浅拷贝




18.Python运行代码

print('Hello
World!')
print('__name__
value: ', __name__)

def main():

print('This message is from main function')

if __name__ ==
'__main__':

main()

print_module.py的代码如下:
import print_func
print("Done!")

Hello World!  __name__ value: print_func  Done!
当运行模块的时候,__name__等于“__main__”;如果import到其他模块中,则__name__等于模块名称(不包含后缀.py)
发表于 2019-06-12 09:43:34

19.Python常识

Python2 中除法默认向下取整,因此 1/2 = 0,为整型。 Python2 print 不用括号
而 Python3 中的除法为正常除***保留小数位,因此 1/2 = 0.5,为浮点型。

  1. Python 是弱类型脚本语言,变量就是变量,没有特定类型,因此不需要声明
  2. 但每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。
  3. 用 del 语句可以释放已创建的变量(已占用的资源)。




20.Java赋值语句

int i =1000;
float f = 45.0;  错误,没有f
char s = ‘\u0639’错误  选择没有;
Object o = ‘f’; 可以把任何一种数据类型的变量赋给Object类型的变量,因为java所有类默认继承Object,基本数据类型赋值给Object会先装箱,装箱之后就是Object的子类了
String s = "hello,world\0";
Double d = 100; 错误
首先,double d =100; 是不会错的,double是8个字节64位,int 是4个字节,32位。所以int转double,32位转64位,肯定是不会错的。那F项错在哪里?仔细看是Double 不是double哦,所以这道题考的是java自动装箱,对于Integer和Double的自动装箱,只能装对应的数据类型,不对应就会报错。java中100默认是int型,而不是byte,short和long;100.0默认是double,而不是float。
自动装箱规则: Double Integer Long Float只接受自己基础类型的数据(double int long float) Character Short Byte 都可以接受char int short byte四种基础数据类型直接封装



long test=012
float f=-412
int other =(int)true
double d=0x12345678
byte b=128
选ABD
A和B中long和float,正常定义需要加l和f,但是long和float属于基本类型,会进行转化,所以不会报出异常。AB正确
boolean类型不能和任何类型进行转换,会报出类型异常错误。所以C错。
D选项可以这样定义,D正确。
E选项中,byte的取值范围是-128—127。报出异常: cannot convert from int to byte.所以E选项错误


21.Java接口和抽象类

1、接口是一种约束和规范,是一种更加更高级的抽象类,抽象类的方法必须是公开的,因为要给人继承和使用啊,不用public,别人怎么看得到,所以在接口实现时,定义的方法修饰符必须是public;因此子类在实现接口重写方法时的修饰符必须是public。
2、另外再扩展一下,接口中没有变量(既然是约束和规范,怎么能够定义一个大家都可以改的东西呢?),只能是常量,接口中定义常量默认的修饰符为public static final
3.子类重写父类方法时,方法的访问权限不能小于原访问权限,在接口中,方法的默认权限就是public,所以子类重写后只能是public

正确答案: A B D   你的答案: B D (错误)

抽象类可以有构造方法,接口中不能有构造方法
抽象类中可以有普通成员变量,接口中没有普通成员变量
抽象类中不可以包含静态方法,接口中可以包含静态方法
一个类可以实现多个接口,但只能继承一个抽象类。
含有abstract修饰符的class即为抽象类,abstract类不能创建的实例对象。
含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必是抽象的。
abstract class类中定义抽象方法必须在具体(Concrete)子类中实现,所以,不能有抽象构造方法或抽象静态方法。
如果的子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为abstract类型。
接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。
接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。
下面比较一下两者的语法区别:
1.抽象类可以有构造方法,接口中不能有构造方法。 不能用new实例化
2.抽象类中可以有普通成员变量,接口中没有普通成员变量
3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
4. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然
eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
5. 抽象类中可以包含静态方法,接口中不能包含静态方法
6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
7. 一个类可以实现多个接口,但只能继承一个抽象类。

jdk1.8之前

接口

1.多实现

2.变量类型默认且只能为为public static final

3.函数类型默认且只能为public,只能有public类型的静态成员函数

4.非静态成员函数没有方法体,静态成员函数有方法体

5.子类必须实现所有接口函数

6.可以有main方法;可以new一个接口,需要在方法体中实现所有接口函数

7.没有构造器

抽象类

1.单继承

2.变量类型不限(静态变量+非静态变量)

3.函数类型不限(静态函数+非静态函数)

4.非静态函数包含没有方法体的抽象函数. 有方法体的普通函数

5.子类可以不覆写父类的抽象方法,但子类也要申明为抽象类;子类可以选择覆写父类的非抽象方法

6.可以有main方法;不可以new一个抽象类

7.可以有构造器

Jdk1.8

接口中可以有default类型的方法,实现类可以选择实现该方法

意义:默认方法的主要优势是提供一种拓展接口的方法,而不破坏现有代码。另一个优势为该方法是可选的,子类可以根据不同的需求Override或默认实现。


A、java为单继承,多实现。可以实现多个接口。
B、
接口允许定义成员,但必须是常量。
C、
抽象类和接口类的无法实例化,任何编译器中直接使用new会报错。
D、A,单继承,多实现。


22.在Java中,HashMap中是用哪些方法来解决哈希冲突的?

常用开放定址法和链地址法
开放定址法:当冲突发生时,使用某种探查(亦称探测)技术在散列表中形成一个探查(测)序列。沿此序列逐个单元地查找,直到找到给定 的关键字,或者碰到一个开放的地址(即该地址单元为空)为止(若要插入,在探查到开放的地址,则可将待插入的新结点存人该地址单元)。查找时探查到开放的 地址则表明表中无待查的关键字,即查找失败。
链地址法:将所有关键字为同义词的结点链接在同一个单链表中。若选定的散列表长度为m,则可将散列表定义为一个由m个头指针组成的指针数 组T[0..m-1]。凡是散列地址为i的结点,均插入到以T[i]为头指针的单链表中。T中各分量的初值均应为空指针。当然了,使用链地址***导致get的效率从o(1)降至o(n),所以在Java8中,使用的是平衡树来解决提高效率的。

常见的哈希冲突解决方法:
1.开放地址法
2.链地址法(拉链法)
3.再散列
4.建立一个公共溢出区

23.JavaWEB中有一个类,通知:

HttpSessionAttributeListener:可以实现此侦听器接口获取此web应用程序中会话属性列表更改的通知;

HttpSessionBindingListener:当该对象从一个会话中被绑定或者解绑时通知该对象,这个对象由HttpSessionBindingEvent对象通知。这可能是servlet程序显式地从会话中解绑定属性的结果,可能是由于会话无效,也可能是由于会话超时;

HttpSessionObjectListener:没有该接口API;

HttpSessionListener:当web应用程序中的活动会话列表发生更改时通知该接口的实现类,为了接收该通知事件,必须在web应用程序的部署描述符中配置实现类;

HttpSessionActivationListener:绑定到会话的对象可以侦听容器事件,通知它们会话将被钝化,会话将被激活。需要一个在虚拟机之间迁移会话或持久会话的容器来通知所有绑定到实现该接口会话的属性。


24.try-catch-finally 规则( 异常处理语句的语法规则

1)  必须在 try 之后添加 catch 或 finally 块。try 块后可同时接 catch 和 finally 块,但至少有一个块。

2) 必须遵循块顺序:若代码同时使用 catch 和 finally 块,则必须将 catch 块放在 try 块之后。
3) catch 块与相应的异常类的类型相关。
4) 一个 try 块可能有多个 catch 块。若如此,则执行第一个匹配块。即Java虚拟机会把实际抛出的异常对象依次和各个catch代码块声明的异常类型匹配,如果异常对象为某个异常类型或 其子类的实例,就执行这个catch代码块,不会再执行其他的 catch代码块
5) 可嵌套 try-catch-finally 结构。
6) 在 try-catch-finally 结构中,可重新抛出异常。

7) 除了下列情况,总将执行 finally 做为结束: JVM 过早终止(调用 System.exit(int));在 finally 块中抛出一个未处理的异常;计算机断电、失火、或遭遇病毒攻击

由此可以看出,catch只会匹配一个,因为只要匹配了一个,虚拟机就会使整个语句退出

public class ExceptionTest
{
public void method()
{
try
{
System.out.println("进入到try块");
}
catch (Exception e)
{
System.out.println("异常发生了!");
}
finally
{
System.out.println("进入到finally块");
}
System.out.println("后续代码");
}
public static void main(String[] args)
{
ExceptionTest test = new ExceptionTest();
test.method();
}
}
链接:https://www.nowcoder.com/questionTerminal/f6351ea54cf94fad808b7af7cd18067b
来源:牛客网
try-catch-finally情况分类:
1.若三个代码块都没有return:执行正常,try-->finally ;执行异常 try->catch->finally
2.若try块包含return,finally不包含,执行正常,try->finally,返回值为try设置;若try包含return ,finally也包含return,执行正常 try->finally,返回值被finally块中覆盖;若执行异常,try->catch->finally 返回值仍然被finally覆盖
try中捕获异常才进入catch,否则不进入catch,不管有没有捕获异常
总结:
try { //执行的代码,其中可能有异常。一旦发现异常,则立即跳到catch执行。否则不会执行catch里面的内容 }
catch { //除非try里面执行代码发生了异常,否则这里的代码不会执行 }、
finally { //不管什么情况都会执行,包括try catch 里面用了return ,可以理解为只要执行了try或者catch,就一定会执行 finally }


下面哪些情况可以引发异常:

正确答案: A B C   你的答案: A B (错误)

数组越界
指定URL不存在
使用throw语句抛出
使用throws语句

1、throws出现在方法头,throw出现在方法体 
2、throws表示出现异常的一种可能性,并不一定会发生异常;throw则是抛出了异常,执行throw则一定抛出了某种异常。 
3、两者都是消极的异常处理方式,只是抛出或者可能抛出异常,是不会由函数处理,真正的处理异常由它的上层调用处理。

25.堆,栈

下列Java代码中的变量a、b、c分别在内存的____存储区存放。
1
2
3
4
5
6
7
classA {
    private String a = “aa”;
    public boolean methodB() {
        String b = “bb”;
        final String c = “cc”;
    }
}
a是类中的成员变量,存放在堆区
b、c都是方法中的局部变量,存放在栈区

堆区:只存放类对象,线程共享;
方法区:又叫静态存储区,存放class文件和静态数据,线程共享;
栈区:存放方法局部变量,基本类型变量区、执行环境上下文、操作指令区,线程不共享;



25.java 堆管理,新生代和老年代

Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象。
Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。
这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象,包括内存的分配以及回收。
堆的内存模型大致为:

Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象。
Java 中,堆被划分成两个不同的区域:新生代 ( Young )   1/3 、老年代 ( Old )  2/3。新生代 ( Young ) 又被划分为三个区域:Eden  8/10的新生代、From Survivor  1/10、To Survivor  1/10。
这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象,包括内存的分配以及回收。
堆的内存模型大致为:
从图中可以看出: 堆大小 = 新生代 + 老年代。其中,堆的大小可以通过参数 –Xms、-Xmx 来指定。
本人使用的是 JDK1.6,以下涉及的 JVM 默认值均以该版本为准。
默认的,新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 ),即:新生代 ( Young ) = 1/3 的堆空间大小。
老年代 ( Old ) = 2/3 的堆空间大小。其中,新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为 from 和 to,以示区分。
默认的,Edem : from : to = 8 : 1 : 1 ( 可以通过参数 –XX:SurvivorRatio 来设定 ),即: Eden = 8/10 的新生代空间大小,from = to = 1/10 的新生代空间大小。
JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总是有一块 Survivor 区域是空闲着的。
因此,新生代实际可用的内存空间为 9/10 ( 即90% )的新生代空间。

JVM 内存可简单分为三个区:

1、堆区(heap):用于存放所有对象,是线程共享的(注:数组也属于对象)

2、栈区(stack):用于存放基本数据类型的数据和对象的引用,是线程私有的(分为:虚拟机栈和本地方法栈)

3、方法区(method):用于存放类信息、常量、静态变量、编译后的字节码等,是线程共享的(也被称为非堆,即 None-Heap)

Java 的垃圾回收器(GC)主要针对堆区
方法调用时,会创建栈帧在栈中,调用完是程序自动出栈释放,而不是gc释放

对于JVM内存配置参数:
-Xmx10240m -Xms10240m -Xmn5120m -XXSurvivorRatio=3
,其最小内存值和Survivor区总大小分别是()

正确答案: D   你的答案: D (正确)

5120m,1024m
5120m,2048m
10240m,1024m
10240m,2048m

-Xmx10240m:代表最大堆
 -Xms10240m:代表最小堆
 -Xmn5120m:代表新生代
 -XXSurvivorRatio=3:代表Eden:Survivor = 3    根据Generation-Collection算法(目前大部分JVM采用的算法),一般根据对象的生存周期将堆内存分为若干不同的区域,一般情况将新生代分为Eden ,两块Survivor;    计算Survivor大小, Eden:Survivor = 3,总大小为5120,3x+x+x=5120  x=1024
新生代大部分要回收,采用Copying算法,快!
老年代 大部分不需要回收,采用Mark-Compact算法
基于以上特性,新生代中一般采用复制算法,因为存活下来的对象是少数,所需要复制的对象少,而老年代对象存活多,不适合采用复制算法,一般是标记整理和标记清除算法

jvm中垃圾回收分为scanvenge gc和full GC,其中full GC触发的条件可能有哪些

正确答案: C D E   你的答案: B C E (错误)

栈空间满
年轻代空间满
老年代满
持久代满
System.gc()
1,新生代:(1)所有对象创建在新生代的Eden区,当Eden区满后触发新生代的Minor GC,将Eden区和非空闲Survivor区存活的对象复制到另外一个空闲的Survivor区中。(2)保证一个Survivor区是空的,新生代Minor GC就是在两个Survivor区之间相互复制存活对象,直到Survivor区满为止。
2,老年代:当Survivor区也满了之后就通过Minor GC将对象复制到老年代。老年代也满了的话,就将触发Full GC,针对整个堆(包括新生代、老年代、持久代)进行垃圾回收。
3,持久代:持久代如果满了,将触发Full GC。

26.super

根据以下代码段,执行new Child("John", 10); 要使数据域data得到10,则子类空白处应该填写(    )。

class Parent {

private int data;

public Parent(int d){ data = d; }

}

class Child extends Parent{

String name;

public Child(String s, int d){

___________________

name = s;

}

}

正确答案: D   你的答案: C (错误)

data = d;
super.data = d;
Parent(d);
super(d);
1.子父类存在同名成员时,子类中默认访问子类的成员,可通过super指定访问父类的成员,格式:super.xx (注:xx是成员名);
2.创建子类对象时,默认会调用父类的无参构造方法,可通过super指定调用父类其他构造方法,格式:s uper(yy) (注:yy是父类构造方法需要传递的参数)
data可是父类的私有属性
1.super可以访问父类中public、default、protected修饰的成员变量,不能访问private修饰的成员变量。格式为super.成员名称。
2.super可以访问父类中public、default、protected修饰的实例方法,不能访问private修饰的实例方法。格式为super.实例方法。
3.super可以访问父类中public、default、protected修饰的构造方法,不能访问private修饰的构造方法,格式为super(参数).

27.关键字保留字

1、null、true、false 是 Java 中的显式常量值,并不是关键字 或 保留字

2、sizeof 是 C/C++ 中的方法,Java 中并没有这个方法,也没有该关键字 或 保留字

3、implements 和 instanceof 都是 Java 中的关键字

java中true ,false , null在java中不是关键字,也不是保留字,它们只是显式常量值,但是你在程序中不能使用它们作为标识符。
其中const和goto是java的保留字。java中所有的关键字都是小写的,还有要注意true,false,null, friendly,sizeof不是java的关键字,但是你不能把它们作为java标识符用

Java中的关键字有哪些?
答:1)48个关键字:abstract、assert、boolean、break、byte、case、catch、char、class、continue、default、do、double、else、enum、extends、final、finally、float、for、if、implements、import、int、interface、instanceof、long、native、new、package、private、protected、public、return、short、static、strictfp、super、switch、synchronized、this、throw、throws、transient、try、void、volatile、while。
2)2个保留字(现在没用以后可能用到作为关键字):goto、const。
3)3个特殊直接量:true、false、null。 


28.Java 集合

Java中的集合类型:Vector、Set、List





而Array是数组,并不继承Collection接口。

28。类之间存在以下几种常见的关系:

正确答案: A B C   你的答案: A C (错误)

“USES-A”关系
“HAS-A”关系
“IS-A”关系
“INHERIT-A”关系
USES-A:依赖关系,A类会用到B类,这种关系具有偶然性,临时性。但B类的变化会影响A类。这种在代码中的体现为:A类方法中的参数包含了B类。
关联关系:A类会用到B类,这是一种强依赖关系,是长期的并非偶然。在代码中的表现为:A类的成员变量中含有B类。
HAS-A:聚合关系,拥有关系,是关联关系的一种特例,是整体和部分的关系。比如鸟群和鸟的关系是聚合关系,鸟群中每个部分都是鸟。
IS-A:表示继承。父类与子类,这个就不解释了。
要注意:还有一种关系:组合关系也是关联关系的一种特例,它体现一种contains-a的关系,这种关系比聚合更强,也称为强聚合。它同样体现整体与部分的关系,但这种整体和部分是不可分割的。


28.重写和重载

方法重写严格把握五点:
三同、一大、一小。具体内容以及与方法重载的区别见下:
方法重写
参数列表必须完全与被重写方法的相同; 
返回类型必须完全与被重写方法的返回类型相同; 
方法名相同;
以上为三同;

访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为public,那么在子类中重写该方法就不能声明为protected。 
此为一大;

重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。 

此为一小;

构造方法不能被重写。 
如果不能继承一个方法,则不能重写这个方法。 

方法重载
被重载的方法必须改变参数列表(参数个数或类型或顺序不一样); 
被重载的方法可以改变返回类型; 
被重载的方法可以改变访问修饰符; 
被重载的方法可以声明新的或更广的检查异常; 
方法能够在同一个类中或者在一个子类中被重载。 
无法以返回值类型作为重载函数的区分标准。



28.数据库的键

候选键(Candidate Key):一个或者多个属性的集合,可以唯一确定实体的一个实例;
主键(Primary Key):从候选键中,选中用来作为唯一标识的属性或者属性组被称为主键;
可选键(Alternative Key):候选键中没有选中的其他键,称为可选键;
而表的外键是另一表的主键, 外键可以有重复的, 可以是空值。

29.数据库的插入

数据库的插入操作用insert而不是add
成绩类型为数值型,不需要加引号。
因此SQL语句为:INSERT INTO S VALUES(’张二’,’化学’,80)

30。数据库的设计过程

数据库设计通常分为6个阶段
1需求分析:分析用户的需求,包括数据、功能和性能需求;
2概念结构设计:主要采用E-R模型进行设计,包括画E-R图
3逻辑结构设计:通过将E-R图转换成表,实现从E-R模型到关系模型的转换
4数据库物理设计:主要是为所设计的数据库选择合适的存储结构和存取路径
5数据库的实施:包括编程、测试和试运行;
6数据库运行与维护:系统的运行与数据库的日常维护。),主要讨论其中的第3个阶段,即逻辑设计。

补充:
E-R图也称实体-联系图(Entity Relationship Diagram),提供了表示实体类型、属性和联系的方法
就数据库而言,实体往往指某类事物的集合。
实体之间的联系有一对一、一对多、多对多。
属性为实体或联系在某一方面的特征。

关键码包括   起导航数据作用
(1)超键(Super Key)
(2)候选键(Candidate Key)
(3)主键(Primary Key)
(4)外键(Foreign Key)


数据库管理系统是位于用户和OS之间的一层管理 软 件 ,数据库系统是由数据库,硬件,软件,数据库管理员组成。

31 锁

锁的类型有三种:

共享(S)锁:多个事务可封锁一个共享页;任何事务都不能修改该页; 通常是该页被读取完毕,S锁立即被释放。

排它(X)锁:仅允许一个事务封锁此页;其他任何事务必须等到X锁被释放才能对该页进行访问;X锁一直到事务结束才能被释放。该事务既可读又可写

更新(U)锁:用来预定要对此页施加X锁,它允许其他事务读,但不允许再施加U锁或X锁;当被读取的页将要被更新时,则升级为X锁;U锁一直到事务结束时才能被释放。


以下( )封锁违反两段锁协议。

正确答案: D   你的答案: C (错误)

Slock A … Slock B … Xlock C ………… Unlock A … Unlock B … Unlock C
Slock A … Slock B … Xlock C ………… Unlock C … Unlock B … Unlock A
Slock A … Slock B … Xlock C ………… Unlock B … Unlock C … Unlock A
Slock A …Unlock A ……Slock B … Xlock C ………...Unlock B … Unlock C


只要注意两段锁的根本概念:两段锁协议是指所有事务必须分两个阶段对数据项加锁和解锁。所以ABC都是正确的。
两段锁协议是指每个事务的执行可以分为两个阶段:生长阶段(加锁阶段)和衰退阶段(解锁阶段)。
加锁阶段:在该阶段可以进行加锁操作。在对任何数据进行读操作之前要申请并获得S锁,在进行写操作之前要申请并获得X锁。加锁不成功,则事务进入等待状态,直到加锁成功才继续执行。
解锁阶段:当事务释放了一个封锁以后,事务进入解锁阶段,在该阶段只能进行解锁操作不能再进行加锁操作。


两端锁
两段锁协议(Two-Phase Locking――2PL)

两段锁协议规定所有的事务应遵守的规则:
① 在对任何数据进行读、写操作之前,首先要申请并获得对该数据的封锁。
② 在释放一个封锁之后,事务不再申请和获得其它任何封锁。
即事务的执行分为两个阶段:
第一阶段是获得封锁的阶段,称为扩展阶段。
第二阶段是释放封锁的阶段,称为收缩阶段。

定理:若所有事务均遵守两段锁协议,则这些事务的所有交叉调度都是可串行化的。
对于遵守两段协议的事务,其交叉并发操作的执行结果一定是正确的。值得注意的是,上述定理是充分条件,不是必要条件。一个可串行化的并发调度的所有事务并不一定都符合两段锁协议,存在不全是2PL的事务的可串行化的并发调度。
同时我们必须指出,遵循两段锁协议的事务有可能发生死锁。

此时事务T1 、T2同时处于扩展阶段,两个事务都坚持请求加锁对方已经占有的数据,导致死锁。
为此,又有了一次封锁法。一次封锁法要求事务必须一次性将所有要使用的数据全部加锁,否则就不能继续执行。因此,一次封锁法遵守两段锁协议,但两段锁并不要求事务必须一次性将所有要使用的数据全部加锁,这一点与一次性封锁不同,这就是遵守两段锁协议仍可能发生死锁的原因所在。






32 层次模型

层次模型采用树型结构表示数据与数据间的联系。在层次模型中,每一个节点表示记录类型(实体),记录之间的联系用节点之间的连线表示,并且根节点以外的其他节点有且仅有一个双亲节点。层次模型不能直接表示多对多联系,一对多
若要表示多对多的联系,可采用如下两种方法:
・ 冗余节点法――两个实体的多对多的联系转换为两个一对多的联系,该方法的优点是节点清晰,允许节点改变存储位置,缺点是需要额外的存储空间,有潜在的数据不一致性。
・ 虚拟节点分解法――将冗余节点转换为虚拟节点,虚拟节点是一个指引元,指向所代替的节点,该方法的优点是减少对存储空间的浪费,避免数据不一致性,缺点是改变存储位置可能引起虚拟节点中指针的修改。

关系数据模型的逻辑结构是关系
层次数据模型的逻辑结构是树
网状数据结构的逻辑结构是图


33.关系数据库中的选择,投影,连接,除法

选择

定义:在关系中选择在指定属性上有确定值的关系的子集。表示为:
选择运算公式
选择运算是选择关系中行的子集,即选择满足条件的元组

例:
1.查询信息系(IS系)全体学生
σ Sdept=‘IS’(Student)
2.查询年龄小于20岁的学生
σ Sage<20(Student)

选择运算的特性:
选择运算特性


投影

投影是选取关系中列的子集。设模式R上关系r,X是R上属性的子集(x就是列),r到 X上的投影r`表示为:
投影
投影操作是从列的角度进行行的运算。投影的结果不是原来的关系,是X中的几列属性。

特别注意

由于投影之后不仅取消了原关系中的某些列,而且还可能取消某些元组,因为取消了某些属性列之后,就可能出现重复行,投影结果中不应该包含重复行

例子:查询学生关系Student中都有哪些系,即查询关系Student上所在系属性上的投影
Student关系如图所示:

Sname Sdept
李勇 CS
刘晨 CS
王小明 MA
张超 IS

求 : π Sdept(Student)

因为Student关系原来有4个元组,但是我们的投影结果需要取消重复的CS元组,因此投影结果只有三个元组:
Sdept
CS
MA
IS

投影的特性
投影特性


连接(Join):自然连接,等值连接

定义: 连接也称为θ连接。它是从两个关系的笛卡尔积中选取属性间满足一定条件的元组。
记作:
连接运算
(θ为比较符: >,<,≥,≤,=,≠)

1.等值连接

θ为 = 符号的连接运算称为等值连接。它是从关系R与S的广义笛卡尔积中选取A , B 属性值相等的那些元组。
等值连接
(被水印遮住的地方是A=B)

2.自然连接

自然连接是一种特殊的等值连接。它要求两个关系中进行比较的分量必须是同名的属性组,并且在结果中把重复的属性列去掉

表示为: R⋈S={t r⌒ts |tr∈R∧ts∈S∧tr[B]=ts[B]}

(自然连接也可看作是在广义笛卡尔积R×S中选出同名属性上符合相等条件元组,再进行投影,去掉重复的同名属性,组成新的关系。)

所以等值连接和自然连接的区别是

自然连接是去除了重复的属性列的!

例题

求R和S的自然连接,等值连接,以及非等值连接R[C<e> R :</e>

A B C
a1 b1 5
a1 b2 6
a2 b3 8
a2 b4 12

S:

B E
b1 3
b2 7
b3 10
b3 2
b5 2

自然连接:R⋈S

A B C E
a1 b1 5 3
a1 b2 6 7
a2 b3 8 10
a2 b3 8 2

等值连接:R[R.B=S.B]S

A R.B C S.B E
a1 b1 5 b1 3
a1 b2 6 b2 7
a2 b3 8 b3 10
a2 b3 8 b3 2

非等值连接:R[C<e>
A R.B C S.B E
a1 b1 5 b2 7
a1 b1 5 b3 10
a1 b2 6 b2 7
a1 b2 6 b3 10
a2 b3 8 b3 10
</e>

除法运算(division)

设关系R除以关系S的结果为关系T,则T包含所有在R但不在S中的属性及其值,且T的元组与S的元组的所有组合都在R中

除法的结果可以用计算象集的方法来解决,以一道题为例来说明怎么求除法

例题:已知关系R和S如下,求R➗S的结果
例题

第一步 : 因为R÷S所得到的属性值 是包含于R,但是S不包含的属性, 所以R➗S得到的属性列有(A,B),S在(C,D)属性上的投影为{(c1,d1),(c2,d2)}
第二步 : 关系R中,AB属性可以取值为={(a1,b1),(a2,b2),(a3,b3)}
第三步 : 求象集
  • (a1,b1)={(c1,d1),(c2,d2),(c3,d3)}
  • (a2,b2)={(c2,d2)}
  • (a3,b3)={(c1,d1),(c2,d2)}
第四步: 从第三步中可以发现,有象集(a1,b1)和(a3,b3)包含了S在(C,D)属性上的投影,所以R÷S={(a1,b1),(a3,b3)}
A B
a1 b1
a3 b3

33.数据库与数据库管理系统

数据库系统的特点:
1.数据结构化 2.数据的共享性高、冗余度低且易扩充 3.数据独立性高 4.数据由数据库管理系统统一管理和控制
其中数据库管理系统有以下几个控制功能:
数据的安全性保护、数据的完整性检查、并发控制、数据库恢复

1) 实体完整性:规定表的每一行在表中是惟一的实体。举例:设属性A是关系R的主属性,则属性A不能取空值(NULL) 2) 域完整性:是指表中的列必须满足某种特定的数据类型约束,其中约束又包括取值范围、精度等规定。
3) 参照完整性:是指两个表的主关键字和外关键字的数据应一致,保证了表之间的数据的一致性,防止了数据丢失或无意义的数据在数据库中扩散。
4) 用户定义的完整性:不同的关系数据库系统根据其应用环境的不同,往往还需要一些特殊的约束条件。用户定义的完整性即是针对某个特定关系数据库的约束条件,它反映某一具体应用必须满足的语义要求。

数据库系统的三级模式结构是指数据库系统是由模式、外模式和内模式三级构成的。
(1)模式 模式也称逻辑模式或概念模式,是数据库中全体数据的逻辑结构和特征的描述,是所有用户的公共数据视图。 模式实际上是数据库数据在逻辑级上的视图。一个数据库只有一个模式。定义模式时不仅要定义数据的逻辑结构,而且要定义数据之间的联系,定义与数据有关的安全性、完整性要求。
(2)外模式 外模式也称用户模式,它是数据库用户能够看见和使用的局部数据的逻辑结构和特征的描述,是数据库用户的数据视图,是与某一应用有关的数据的逻辑表示。 外模式通常是模式的子集。一个数据库可以有多个外模式。应用程序都是和外模式打交道的。外模式是保证数据库安全性的一个有力措施。每个用户只能看见和访问所对应的外模式中的数据,数据库中的其余数据对他们是不可见的。
(3)内模式 内模式也称存储模式,一个数据库只有一个内模式。它是数据物理结构和存储方式的描述,是数据在数据库内部的表示方式。例如,记录的存储方式是顺序结构存储还是B树结构存储;索引按什么方式组织;数据是否压缩,是否加密;数据的存储记录结构有何规定等。


逻辑独立性是外模式不变,模式改变时,如增加新的关系,新的属性,改变属性的数据类型,由数据库管理员对各个外模式/模式的映像做相应改变,可以使得外模式不变,因为应用程序依据外模式编写的,所以外模式不变,应用程序也不变,即保证了逻辑独立

物理独立性是模式不变,内模式改变,如数据库存储结构发生改变,选用另一种数据结构,由数据库管理员对各个模式/内模式的映像做相应改变,可以使得模式不变 ,从而保证了应用程序也不变


34.范式

定义学生、教师和课程的关系模式STC(SNO,SN,SA,TN,CN,G),其中的六个属性分别为学生的学号、姓名、年龄、教师的姓名、课程名以及学生的成绩,则该关系为(  )。

第一范式,所有列必须是原子项,即不可分割,不能存在数组集合等。
第二范式,在满足第一范式的基础上,所有非主键列必须完全依赖与主键,如从学生的学号可以推算出学生的姓名 年龄,但是却无法推断出老师和课程名。因此不满足第二范式。
第三范式:要求非主键列与主键直接相关,不能相互依赖,比如存在年龄分析等与年龄有关的列。
BCNF范式:所有属性都不传递依赖于关系的任何候选键。

35.数据库的修改

修改表结构包括:增加字段、删除字段、增加约束、删除约束、修改缺省值、修改字段数据类型、重命名字段、重命名表等。这些操作都是用 alter table 命令来完成。常用用法如下:

1、增加字段:ALTER TABLE 表名      ADD 字段名 字段类型;

2、删除字段:ALTER TABLE 表名      DROP COLUMN 字段列名;

3、增加约束:ALTER TABLE 表名 ADD CHECK(字段名<>'')或者 ALTER TABLE 表名 ADD CONSTRAINT 约束名 UNIQUE(字段名);
4、删除约束:ALTER TABLE 表名 DROP CONSTRAINT 约束名;

5、修改字段缺省值:ALTER TABLE 表名 ALTER COLUMN 字段名 SET DEFAULT 默认值;

6、 修改字段数据类型:ALTER TABLE 表名 ALTER COLUMN 字段名TYPE l类型;

7、重命名字段:ALTER TABLE 表名 RENAME COLUMN 旧字段名TO 新字段名;

8、重命名表:ALTER TABLE 表名 RENAME TO 新表名。

ALTER和Modify的区别。
alter 是针对表整体,modify是对表中的某一项字段进行修改。
eg.  alter table table_name modify  id  int;

36 删除

A: drop table book 是删除整个表,题目的潜在意思是删除表中的数据而并非删除整个表。因此A错。
B: truncate table book 是删除表中的数据,删除速度比delete更快,无法撤回(回退)。
C: delete from book  删除数据表中的数据,可以回退,可添加where 子句。

37 复合索引

因复合索引为idx_A_B_C,所以查询条件只能是在a,ab,abc,ac才算 使用到索引idx_A_B_C

39数据库分类
MongoDB 属于文档型非关系数据库;
PostgreSQL  关系型数据库
Redis 属于KV键值数据库
HBase 属于列数据库

40. 树

1.在完全二叉树中若某节点N存在左右孩子节点,左节点为2N,右节点为(2N)+1.
则:
根据节点编号求双亲编号:i/2向下取整
求节点i是否有左右子树:
若 2i  <= n(总节点个数)  :i有左子树
若 2i+1 <= n :i有右子树。 

2.假设二叉树的深度为k,则该二叉树最多有2^k - 1个节点,若k为6,则最多有2^6 - 1 = 63个节点,小于65。故该二叉树的深度为7

3.已知一棵树的前序遍历是“GDAFEMHZ”,而中序遍历是“ADEFGHMZ”,求后续遍历是?  
AEFDHZMG
先序遍历第一个G是根节点,然后看中序,G左边的ADEF属于G的左子树,HMZ属于G的右子树。
先序第二个为D,说明左子树的根节点为D,然后看中序,A属于D的左子树,EF属于D的右子树。
以此类推


4.已知完全二叉树的第七层中有10个叶子结点,则整个二叉树中最多有:
第七层最多能容2^6=64个结点。
根据题意,第7层有10个叶子结点
①结点最少的情况:第七层仅有10个结点。前六层共有2^6-1=63个结点。加上第7层的10个叶子结点,就是73个结点。即题中描述的二叉树最少有73个结点
②结点最多的情况:第七层有64个结点,其中有54个结点有孩子结点,剩下的10个结点为叶子结点。前七层总计结点数为2^7-1=127个结点。第八层有54*2=108个结点。两者相加为235个结点。即题中描述的二叉树最多有235个结点。
因此题中描述是错误的。谨记!!!完全二叉树最后两层都可能有叶结点

5.若X 是后序线索二叉树中的叶结点,且 X 存在左兄弟结点 Y,则 X 的右线索指向的是( )
后序遍历,左右根,X左线索指前驱,右线索指后继,X有左兄弟,那么X的后继就是父结点

6.

分别以下列序列构造二叉排序树,与用其它三个序列所构造的结果不同的是()

正确答案: D   你的答案: 空 (错误)

(100,80,60,90,120,130,110)
(100,120,110,130,80,60,90)
(100,80,90,60,120,110,130)
(100,60,80,90,120,110,130)
二叉排序树,左子树比根节点小,右子树比根节点大,所以对二叉排序树进行中序遍历,便可得到一个按关键字排序的序列

二叉搜索树中序遍历的结果一定是从小到大的有序序列

除了D 其他都是满二叉树

就查找的平均时间性能而言,二叉排序树上的查找与折半查找类似,但就维护表的有序性而言,二叉排序树更高效,因为它无需移动节点,只需修改指针即可完成二叉排序树的插入和删除操作。

二叉排序树查找在在最坏的情况下,需要的查找时间取决于树的深度:

当二叉排序树接近于满二叉树时,其深度为 l o g 2 n    最坏情况下查找时间为O( l o g 2 n)    与折半查找是同数量级的。
最坏情况下 当二叉树形成单枝树时,其深度为n,最坏情况下查找时间为O(n),与顺序查找属于同一数量级。
所以为了保证二叉排序树查找有较高的查找速度,希望该二叉树接近于满二叉树,或者二叉树的每一个节点的左、右子树深度尽量相等
————————————————
版权声明:本文为CSDN博主「蓝墨49」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq447995687/article/details/95376501

  • 平衡二叉树定义
    平衡二叉树(Balanced Binary Tree),它是一棵空树,或者是具有以下性质:
  1. 它的左右两个子树的深度差的绝对值不超过1;
  2. 它的左右两个子树也分别是平衡二叉树。
因为平衡二叉树上任何节点的左、右子树的深度之差都不会超过1,可以证明它的深度和n个节点的完全二叉树的深度⌊ l o g 2 n ⌋ +1是同数量级的。因此,它的平均查找次数也是和⌊ l o g 2 n ⌋ +1同数量级的。
————————————————
版权声明:本文为CSDN博主「蓝墨49」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq447995687/article/details/95376501


7.二叉树的三种遍历算法区别仅在于对树根、左右子树访问先后顺序的不同,这种说法()
错误
三种方法的遍历都是根左右,只是打印顺序不同,前序是判断当if(前节点==NULL)return;else(打印,左递归,右递归)。中序是if(前节点==NULL)return;else(左递归,打印,右递归)。后序是判断当if(前节点==NULL)return;else(左递归,右递归,打印)。

8.以数组存储,是按照层次序来保存的。
对于以下用数组存储的二叉树A B C D E采用中序和前序遍历的结果是()

在一棵二叉排序树上查找值为35的数据,以下比较的数据序列正确的为

正确答案: D   你的答案: 空 (错误)

28、36、18、46、35
18、36、28、46、35
46、28、18、36、35
46、36、18、28、35
选D
A.【28,?】→【28,36】→18不在这个区间,错误
B.【18,?】→【18,36】→【28,36】→46不在这个区间,错误
C.【?,46】→【28,46】→18不在这个区间,错误
D.【?,46】→【?,36】→【18,36】→【28,36】→找到35
35<46 往左 36
35<36 往左 18
35>18 往右 28
35>28 往右找到




以下是一个tree的遍历算法,queue是FIFO队列,请参考下面的tree,正确的输出是

1
2
3
4
5
6
7
8
9
10
queue.push(tree.root)
while(true){
   node=queue.pop( );
   output(node.value);//输出节点对应数字
   if(null= =node)
      break;
   for(child_node in node.children){
      queue.push(child_node);
   }
}

正确答案: A   你的答案: B (错误)

1234567
1245367
1376254
1327654
这是二叉树的层次遍历。(输出结果跟加入队列的顺序相同)
while的第一次循环首先输出root节点,为1
在while的for循环里把2,3加入队列中
while第二次循环,输出2,在while的for循环里把2的两个子节点4,5加入队列
while第三次循环,输出3,在while的for循环里 把2的两个子节点6,7加入队列
再以后的while循环中,依次输出队列中的元素,这些元素都是叶子节点,for循环不再起作用
总的输出结果是1234567


完全二叉树是由满二叉树而引出来的,若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数(即1~h-1层为一个满二叉树),第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。

堆一般都是用完全二叉树来实现的。


若以{4,7,8,10,12}作为叶子节点的权值构造哈弗曼树,则其带权路径长度是()
一.哈弗曼树的构建
    每次在所有的数值中选择最小的两个值,相加后作为新的值放入原来的集合中,重复该过程
    {4,7,8,10,12}构建的哈弗曼树如下图
                41
        23            18
    12     11    8       10
           4    7
二.带权路径
    在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。
    树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL。
三.本题的计算
    WPL = 12*2 + 4*3 +7*3 + 8*2 + 10*2 =93




41.线性表

线性表一般有两种存储形式,一种是基于顺序表的存储,一种是基于链表的存储。
采用顺序表存储,则必须占用一片连续的内存空间,逻辑上相邻的元素,物理存储位置上也相邻。采用链表存储,则逻辑上相邻的两个元素,物理位置上不一定相邻
采用顺序表的存储,便于随机的存取,但是插入和删除比较耗时。采用链式存储,便于插入和删除,无法随机的存取。

串又称为字符串,是一种特殊的线性表,其特殊性体现在数据元素是一个字符,也就是说串是一种内容受限的线性表。(栈和队列是操作受限的线性表)

假设以行优先顺序存储三维数组A[5][6][7],其中元素A[0][0][0]的地址为1100,且每个元素占2个存储单元,则A[4][3][2]的地址是()
那么A[4][3][2]中4、3、2分别对应这个点的层数、行号、列号
位置为4*(6*7)+3*7+2=191
每个元素两个存储单元,最终结果为191*2+1100=1482

表分为顺序表和链表。
A、顺序表的特点就是随即存取,所以访问节点的时间复杂度为O(1)。 
B、插入一个节点,那么这个节点之后的所有节点都分别要向后移动一个,所以时间复杂度为O(n)。 
C、同样,删除一个节点,那么后面的所有节点都需要向掐移动一个,所以时间复杂度为O(n)。
D、排序。。 常见的排序方法中最快的也是O(n),即使是桶排序,也是不可能达到O(1)的。



42.图

有向完全图:n(n-1) 
无向完全图:n(n-1)/2 至多  至少应该有  n-1  条边

已知无向图G含有16条边,其中度为4的顶点个数为3,度为3的顶点个数为4,其他顶点的度均小于3。图G所含的顶点个数至少是 11
无向图边数的两倍等于各顶点度数的总和。由于其他顶点的度均小于3,可以设它们的度都为2,设它们的数量是x,可列出这样的方程4*3+3*4+2*x=16*2,解得x=44+3+4=11

以下哪些算法可以检测一个有向图中是否存在环( )
深度优先遍历
广度优先遍历
拓扑排序
关键路径算法
正确答案: A C  
DFS的时候,如果要访问的元素已经访问过,它在当前的栈内还没出栈,那么就是有环。BFS不行是因为可能有多个节点指向该节点,不一定是因为有环。
拓扑排序会循环执行以下两步:
(1) 选择一个入度为0的顶点,输出
(2) 从图中删除此顶点以及所有的出边
循环结束后,若输出的顶点数小于网中的顶点数,则说明有回路


一个无向图G=(V,E),顶点集合V={1,2,3,4,5,6,7},边集合E={(1,2), (1,3),(2,4), (3,4), (4,5),(4,6), (5,7) , (6,7)},从顶点1出发进行深度优先遍历,可得到的顶点序列是 ( )

正确答案: B C D   你的答案: D (错误)

1,2,3,4,5,6,7
1,2,4,3,6,7,5
1,3,4,5,7,6,2
1,2,4,6,7,5,3

首先画出如上所示的图。
从节点1出发有两种选择,要么2要么3。
所谓深度优先遍历是指从一个节点出发,一个走到其中邻居节点,将该邻居节点标记为已遍历,然后从该节点出发,重复上述步骤,知道遇到节点的出度为0或,节点的邻居都已遍历,再返回到最开始出发的节点,找到其未遍历的另一个邻居节点,重复上面的步骤即可。

这个题目容易出错的是,要注意节点4,它有三个邻居节点,分别是3、5、6,因此选项BCD都是正确的答案。但A肯定不是,因为2的邻居存在且不为3。



43.hash

HASH 函数冲突处理方式包括:

  1. 开放定址法
  2. 再哈希法
  3. 链地址法
  4. 设置公共溢出区法



44.堆

下列哪一个关键码序列不符合堆的定义?

正确答案: C   你的答案: 空 (错误)

A、C、D、G、H、M、P、Q、R、X
A、C、M、D、H、P、X 、G、0、R
A、D、P、R、C、Q、X 、M、H、G
A、D、C、M、P、G、H、X 、R、Q
可以看出答案都是小堆关键码序列,根据小堆的定义, 
K[i]<= K[2i] 
K[i]<= K[2i+1] 
C选项中关键码序列用完全二叉树表示后很容易看出,结点值d大于了左子结点值c



关于堆排序复杂度分析的叙述中正确的是( )

正确答案: A B C D   你的答案: A B C D (正确)

堆排序的时间复杂度为O(nlogn)
整个构建堆的时间复杂度为O(n)
堆排序的空间复杂度为O(1)
堆排序是一种不稳定的排序算法



45.栈

设链式栈中结点的结构为(data ,link),且top是指向栈顶的指针,若想在链式栈的栈顶插入一个由指针s所指的结点,则应执行(  )操作。

正确答案: C   你的答案: 空 (错误)

top->link=s; 栈顶的下一个节点指向s,原栈中数据丢失。错误
s->link=top->link; top->link=s; 相当于把s放到了top节点后当作第二节点。错误
s->link=top; top=s; s的link指向原top,新的top指向s。正确
s->link=top; top=top->link; 把s放到头节点之前,再更新头节点为原第二节点,s和原top丢失。错误

在递归算法执行过程中,计算机系统必定会用到的数据结构是( ) 栈
栈的特点是“先进后处,后进先出”,在程序执行过程中,主程序先进栈,被调用的程序后进栈;当被调用程序结束后,先出栈,最后主程序运行结束了,主程序才出栈。


队列

循环队列

设立一个队首指针front ,一个队尾指针rear ,分别指向队首和队尾元素。
基本操作
◆ 初始化:front=rear=0。
◆ 队列为空:front=rear。
◆ 队满:(rear + 1) % MaxSize == fornt
◆ 入队:将新元素插入rear所指的位置,然后rear加1。
rear=(Q->rear+1)%maxQueueSize;
◆ 出队:删去front所指的元素,然后加1并返回被删元素。
sq.front=(sq.front+1)% maxsize;

◆ 取队首元素:返回fornt指向的元素值


46.数组和指针

下列关于数组与指针的区别描述正确的是?

正确答案: B   你的答案: 空 (错误)

数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。
用运算符sizeof 可以计算出数组的容量(字节数)
指针可以随时指向任意类型的内存块。
用运算符sizeof 可以计算出指针所指向内容的容量(字节数)
A.堆上创建动态数组
B.sizeof(数组名)就是数组的容量
C.const指针不可以
D. char* str = "hello"; sizeof(str)不能计算出内容的容量,只是指针的容量。

下面程序段的运行结果是()
1
2
3
4
5
6
7
intmain(intargc, char*argv[])
{
    char*s = "abcdefg";
    s += 2;
    fprintf(stderr, "%d\n", s);
    return0;
}

正确答案: C   你的答案: C (正确)

cde
字符"c"
字符"c"的地址
不确定
指针s指向的是字符串的首地址,也就是字符‘a’的地址
s+=2使得s指向字符‘c’
printf函数中使用%d做控制,要输出的是整型数字,也就是字符‘c’的地址

如果要输出字符‘c’,可用
1
fprintf(stderr, "%c\n", *s);
如果要输出剩余字符串,可用
1
fprintf(stderr, "%s\n", s);




47.排序算法

排序方法    平均时间    最好时间    最坏时间
桶排序(不稳定)    O(n)    O(n)    O(n)
基数排序(稳定)    O(n)    O(n)    O(n)
归并排序(稳定)    O(nlogn)    O(nlogn)    O(nlogn)
快速排序(不稳定)    O(nlogn)    O(nlogn)    O(n^2)
堆排序(不稳定)    O(nlogn)    O(nlogn)    O(nlogn)
希尔排序(不稳定)    O(n^1.25)          
冒泡排序(稳定)    O(n^2)    O(n)    O(n^2)
选择排序(不稳定)    O(n^2)    O(n^2)    O(n^2)
直接插入排序(稳定)    O(n^2)    O(n)    O(n^2)


设一组初始记录关键字的长度为8,则最多经过()趟插入排序可以得到有序序列。
注意插入排序是从第二个元素开始向前比(第一个没得比),到最后一个元素。所以一共n-1趟。

设有5000个待排序的记录关键字,如果需要用最快的方法选出其中最小的10个记录关键字,则用下列()方法可以达到此目的。堆排序
快速排序
堆排序
归并排序
插入排序
快速排序、归并排序和插入排序必须等到整个排序结束后才能够求出最小的 10 个数,而堆排序只需要在初始堆的基础上再进行 10 次筛选即可,每次筛选的时间复杂度为 O(log2n) 

直接选择排序的基本思想是:第一次从R[0]~R[n-1]中选取最小值,与R[0]交换,第二次从R[1]~R[n-1]中选取最小值,与R[1]交换,....,第i次从R[i-1]~R[n-1]中选取最小值,与R[i-1]交换,.....,第n-1次从R[n-2]~R[n-1]中选取最小值,与R[n-2]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列。
因此它的时间复杂度固定为O(n^2)

设一组初始关键字记录关键字为(19,15,12,18,21,36,45,10),则以19位基准记录的一趟快速排序结束后的结果为()

正确答案: A   你的答案: 空 (错误)

10,15,12,18,19,36,45,21
10,15,12,18,19,45,36,21
15,10,12,18,19,36,45,21
10,15,12,19,18,45,36,21
一个不断挖坑填坑的过程。
按题意,先把a[0]挖坑,然后从tail开始找第一个小于pivot的值,这里是a[7]=10,把10填到之前的那个坑中,同时a[7]变成来一个坑。再从前往后,找到第一个大于pivot的值a[4]=21,用21填之前的那个坑,并在a[4]挖来个坑。再从a[6]开始向前寻找第一个小于pivot的值。。。然后与前面的相遇了,把pivot填进那个坑就得到最终结果。
pivot=19;  [], 15,12,18,21,36,45,10
                    10 ,15,12,18,21,36,45,[]
                    10,15,12,18,[],36,45,21
最后填坑:  10,15,12,18,19,36,45,21


下列排序算法中,已基本有序却反而变得更复杂的排序算法是:( )。

正确答案: B   你的答案: 空 (错误)

冒泡排序
快速排序
堆排序
简单选择排序
  1. 快排采用分治的思想,第一次循环结束时,它实际上会产生一个轴,轴左边的都小于轴值,右边的都大于轴值,这样通过轴就分成了两个子序列,再对两个子序列递归快排,最终得到排好序的序列。
  2. 快排对越混乱的数据,排序效果越好,现在说一下为什么对一个基本有序的却更复杂,那是因为这样会导致每次轴划分出的两个子序列,一个趋近于1的数量级,一个趋近于n数量级,那么递归快排就近似总是对n做排序,时间复杂度O(n²),而且非常不符合快排的思想。比较好的情况是每次递归大致平分成两个n/2数量级的子序列,时间复杂度O(nlogn)

某学生信息表,设一组表示成绩的关键字序列(24,15,32,28,19,10,40)采用直接插入排序时,当插入记录19到有序表时,为找插入位置需比较次数为(      )
直接插入排序(straight insertion sort)的做法是:
每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。

大概是:24直接放进去                                                                                     24
第一趟   15比24小放到24前面,比较1次                                                 15    24
第二趟   32比24大放24后面,比较1次                                                     15    24     32
第三趟   28比32小,比24大,比较2次                                                     15   24     28     32
第四趟,19比32小,比28小,比24小,比15大,比较4次                       15    19    24     28    32


每个元素距其最终位置不远,直接插入排序不需要移动太多元素,适用于这种情况,效率高
插入排序:如果平均每个元素离最终位置相距c个元素,则其复杂度为O(cn),一共n趟,每次比较c次;
快速排序:最好的、平均的复杂度都是O(nlog(n)),如果每次选择的中间数都最小或最大,那就是最坏的情况,复杂度是O(n*n);所以快速排序和元素的位置没有关系,跟选择的中间数有关
堆排序:复杂度一直是O(nlog(n));
直接选择排序:跟元素位置没有关系,都要遍历n遍,每遍找出最小或最大数来,复杂度是O(n*n);
答案是插入排序。

对下列关键字序列用快速排序法进行排序时,速度最快的情形是()

正确答案: A   你的答案: 空 (错误)

{21,25,5,17,9,23,30}
{25,23,30,17,21,5,9}
{21,9,17,30,25,23,5}
{5,9,17,21,23,25,30}
pivotkey的选择越靠近***,即左右两个子序列长度越接近,排序速度越快。

21正好是序列的正中,所以排除B,D。

A经过一次排序后结果为9,17,5,(21),25,23,30
C经过一次排序后结果为5,9,17,(21),25,23,30
对于子序列9,17,5和5,9,17,后者在有序状态下用快速排序方法的速度没有前者快,答案为A。


Shell排序的执行时间依赖于增量序列。
好的增量序列的共同特征:
① 最后一个增量必须为1;
② 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况。
有人通过大量的实验,给出了较好的结果:当n较大时,比较和移动的次数约在nl.25到1.6n1.25之间。
2.Shell排序的时间性能优于直接插入排序
希尔排序的时间性能优于直接插入排序的原因:
①当文件初态基本有序时直接插入排序所需的比较和移动次数均较少。
②当n值较小时,n和
  
的差别也较小,即直接插入排序的最好时间复杂度O(n)和最坏时间复杂度0(
  
)差别不大。
③在希尔排序开始时增量较大,分组较多,每组的记录数目少,故各组内直接插入较快,后来增量di逐渐缩小,分组数逐渐减少,而各组的记录数目逐渐增多,但由于已经按di-1作为距离排过序,使文件较接近于有序状态,所以新的一趟排序过程也较快。
因此,希尔排序在效率上较直接插入排序有较大的改进。
分割后子序列内部的排序算法是直接插入排序


具有n个整数的数组A=[27,9,14,16,10]使用冒泡排序(Bubble
Sort)算法排序,算法伪代码如下:
 经过三趟排序后,数组A的排列状态将是()

正确答案: A   你的答案: C (错误)

9,10,14,16,27
9,14,16,10,27
9,14,10,16,27
9,16,10,14,27
冒泡排序,简言之,最大的数据往后挪,所以,三次排序之后,最大的三个数会依次排在最后。




48.存储结构

1.存储结构:
  1. 顺序存储
  2. 链式存储
  3. 索引存储
  4. 哈希(或散列)存储
顺序存储的线性表不但逻辑上连续,物理上也连续,可以使用顺序查找法。
链式存储的线性表虽然物理上不一定连续,但逻辑上连续(通过额外的指针表示逻辑相邻关系),也可以使用顺序查找法。

2.若在线性表中采用折半查找法查找元素,该线性表应该:
元素按值有序且采用顺序存储结构
首先折半查找,必须要求地址是连续的,数组,而且有明确的边界。然后还要求数组里面存放的数据是有序的,要不然无异于随机查找。
折半查找要求直接访问到中间节点,而链式存储必须遍历整个链表

49.查找

顺序查找,时间复杂度O(N),是在一个已知无(或有序)序队列中找出与给定关键字相同的数的具***置。原理是让关键字与队列中的数逐个比较,直到找出与给定关键字相同的数为止。

分块查找,时间复杂度O(logN+N/m); 分块查找是折半查找和顺序查找的一种改进方法,分块查找由于只要求索引表是有序的,对块内节点没有排序要求 (块内无序,块间有序),因此特别适合于节点动态变化的情况。
      折半查找虽然具有很好的性能,但其前提条件时线性表顺序存储而且按照关键码排序,这一前提条件在结点树很大且表元素动态变化时是难以满足的。而顺序查找可以解决表元素动态变化的要求,但查找效率很低。如果既要保持对线性表的查找具有较快的速度,又要能够满足表元素动态变化的要求,则可采用分块查找的方法。
      当增加或减少节以及节点的关键码改变时,只需将该节点调整到所在的块即可。在空间复杂性上,分块查找的主要代价是增加了一个辅助数组。

显然,索引表是按关键字非递减顺序排列的。
一般先用二分查找索引表,确定需要查找的关键字在哪一块,然后再在相应的块内用顺序查找。

折半查找,时间复杂度O(logN)  优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。
                  两个条件:1)序列有序;2)可以随机访问

null 顺序查找 二分查找 分块查找
表的结构 有序、无序 有序 块内无序、块间有序
表的存储 顺序、链式 顺序 顺序、链式
平均查找长度 最大 最小 中间
时间复杂度 O(n) O(log2n) 中间



哈希查找,时间复杂度O(1)

所以平均查找速度慢到快:
顺序 分块 折半 哈希

  • 二分查找首先要求数据是有序的,同时要求能随机访问数据元素, 有序数组可以, 链表不行,

  • 二分查找因为每次都是从中间点开始查找,所以最坏情况是目标元素存在于最边缘的情况。最坏为O(LogN)


在154个元素组成有序表进行二分法查找,可能的比较次数为

正确答案: B C D   你的答案: A B (错误)

10
8
4
1
折半查找过程可用二叉树来描述,把有序表中间位置上的结点作为树的根结点,左子表和右子表分别对应树的左子树和右子树。折半查找的过程就是走一条从根节点到被查结点的一条路径,比较的次数就是该路径中结点的个数,即,该结点在树中的层数。 所以该题可以转换为求有154个结点的二叉树有几层,小于等于这个层数的数值就是答案。 又知,深度为K的二叉树最多有2的K次方-1个结点,深度为7的二叉树最多有127个结点,深度为8的二叉树最多有255个结点,所以154个结点的二叉树有8层。
最差的情况下找8次,所以8次及8次以内都有可能找到。


50.旅行商

同等顾客数量下,以下哪个旅行商变种问题的可行解数量最多()

正确答案: D   你的答案: 空 (错误)

旅行商问题(travelling salesman problem)
带时间窗的旅行商问题 (travelling salesman problem with time windows)
有紧前关系的旅行商问题 (travelling salesman problem with precedence constraints)
多旅行商问题 (multiple travelling salesmen problem)

51.共识算法

股权证明算法 英文简写是PoS,委任权益证明算法 英文简写是DPoS。
这两种都是非常高效的算法,比PoW(工作量证明算法)快得多,有效得多。
区块链中,常见的共识算法有 PBFT,Raft,PoW,PoS,DPoS,Ripple等等。
采用  PoS     共识算法的项目有 (未来的)以太坊Ethereum、Peercoin、Nxt等等;
采用  DPoS  共识算法的项目有:BitShares、Steemit、EOS、Lisk、Ark等等。

52.手机解锁

智能手机的手势解锁密码是九宫格3X3的点阵中的一条路径,这条路 径最少连接四个点,最多连接九个点,请问总共有多少种解锁密码?(    )

正确答案: C   你的答案: 空 (错误)

1000种量级
10000种量级
100000种量级
500000种以上