牛客练习笔记-JAVA 9/28

目录

题目:

1.下面哪些类可以被继承?

2、下面有关servlet中init,service,destroy方法描述错误的是?

3.下面哪一项不是加载驱动程序的方法?

4. 下面叙述那个是正确的?()

5.说明输出结果。

6.下面代码输出是?

7.下面几个关于Java里queue的说法哪些是正确的()?

8.关于ThreadLocal类 以下说法正确的是

9.​编辑

10. 在为传统面向对象语言的程序做单元测试的时候,经常用到mock对象。Mock对象通过反射数。请问反射最大程度破坏了面向对象的以下哪个特性?

11.运用下列哪个命令能够获取JVM的内存映像

 12.以下代码的输出结果是?

13.如果希望监听TCP端口9000,服务器端应该怎样创建socket?

14.在java语言中,如果你编写一个多线程序,可以使用的方法是()

15.下面有关servlet和cgi的描述,说法错误的是?

收获知识点总结

1.全选,Object 类中方法及说明如下:

2.线程的生命周期中包含五种状态:初始态、就绪态、运行态、阻塞态、死亡状态。

3.使用泛型的好处

4.CopyOnWriteArrayList的实现原理

5.、线程的创建方式

6.Servlet和CGI(Common Gateway Interface)都是用于处理Web请求的技术,但它们有一些不同之处。

每日一记:

1、你是怎样理解OOP面向对象的

2、你是怎样理解多态的?什么地方用过?

3、sleep和wait在线程里有什么区别?(上海)


题目:

1.下面哪些类可以被继承?

Java.lang.Thread、java.lang.Number、java.lang.Double、java.lang.Math、 java.lang.ClassLoader
Thread
Number
Double
Math
ClassLoader

正确答案: A B E 你的答案:A B E (正确)
题解:
A:Thread可以被继承,用于创建新的线程
B:Number类可以被继承,Integer,Float,Double等都继承自Number类
C:Double类的声明为 public final class Doubleextends Numberimplements Comparable final声明的类不能被继承
D:Math类的声明为 public final class Mathextends Object 不能被继承
E:ClassLoader可以被继承,用户可以自定义类加载器

2、下面有关servlet中init,service,destroy方法描述错误的是?

A.init()方法是servlet生命的起点。一旦加载了某个servlet,服务器将立即调用它的init()方法

service()方法处理客户机发出的所有请求

destroy()方法标志servlet生命周期的结束

servlet在多线程下使用了同步机制,因此,在并发编程下servlet是线程安全的

正确答案: D

题解:

servlet在多线程下其本身并不是线程安全的。

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

3.下面哪一项不是加载驱动程序的方法?

A 通过DriverManager.getConnection方法加载

B 调用方法 Class.forName

C 通过添加系统的jdbc.drivers属性

D 通过registerDriver方法注册

正确答案:A

你的答案:B

参考答案:答案:A DriverManager.getConnection方法返回一个Connection对象,这是加载驱动之后才能进行的

加载驱动方法

1.Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");

2. DriverManager.registerDriver(new com.mysql.jdbc.Driver());

3.System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver");

4. 下面叙述那个是正确的?()

A java中的集合类(如Vector)可以用来存储任何类型的对象,且大小可以自动调整。但需要事先知道所存储对象的类型,才能正常使用。

B 在java中,我们可以用违例(Exception)来抛出一些并非错误的消息,但这样比直接从函数返回一个结果要更大的系统开销。

C java接口包含函数声明和变量声明。

D java中,子类不可以访问父类的私有成员和受保护的成员。

    A.vector是线程安全的ArrayList,在内存中占用连续的空间。初始时有一个初始大小,当数据条数大于这个初始大小后会重写分配一个更大的连续空间。如果Vector定义为保存Object则可以存放任意类型。

    B.try{}catch{}会增加额外的开销

    C.接口中声明的'变量'必须为public final static,所以为常量

    D.子类可以访问父类受保护的成员

    B选项说的情况就是我们自定义异常的情况,请仔细读:我们可以用违例(Exception)来抛出一些并非错误的消息,可以,并非错误的消息。比如我自定义一个异常,若一个变量大于10就抛出一个异常,这样就对应了B选项说的情况,我用抛出异常说明这个变量大于10,而不是用一个函数体(函数体内判断是否大于10,然后返回true或false)判断,因为函数调用是入栈出栈,栈是在寄存器之下的速度最快,且占的空间少,而自定义异常是存在堆中,肯定异常的内存开销大

5.说明输出结果。

1

2

3

4

5

6

7

8

9

10

11

import java.util.Date; 

public class SuperTest extends Date{ 

    private static final long serialVersionUID = 1L; 

    private void test(){ 

       System.out.println(super.getClass().getName()); 

    

      

    public static void main(String[]args){ 

       new SuperTest().test(); 

    

}

A SuperTest                B SuperTest.class

C test.SuperTest        D  test.SuperTest.class

参考答案:C. TestSuper和Date的getClass都没有重写,他们都是调用Object的getClass,而Object的getClass作用是返回的是运行时的类的名字。这个运行时的类就是当前类,所以 super.getClass().getName() 返回的是test.SuperTest,与Date类无关 要返回Date类的名字需要写super.getClass().getSuperclass()

6.下面代码输出是?

1

2

3

double d1=-0.5;

System.out.println("Ceil d1="+Math.ceil(d1));

System.out.println("floor d1="+Math.floor(d1));

答案       Ceil d1=-0.0 floor d1=-1.0

ceil 方法上有这么一段注释:If the argument value is less than zero but greater than -1.0, then the result is negative zero

如果参数小于0且大于-1.0,结果为 -0.0

牛客练习笔记-JAVA 9/28_第1张图片

7.下面几个关于Java里queue的说法哪些是正确的()?

A LinkedBlockingQueue是一个可选有界队列,不允许null值

B PriorityQueue,LinkedBlockingQueue都是线程不安全的

C PriorityQueue是一个无界队列,不允许null值,入队和出队的时间复杂度是O(log(n))

D PriorityQueue,ConcurrentLinkedQueue都遵循FIFO原则

A、LinkedBlockingQueue是一个基于节点链接的可选是否有界的阻塞队列,不允许null值。
B、LinkedBlockingQueue是一个线程安全的阻塞队列,实现了先进先出等特性。
C、PriorityQueue是一个***队列,不允许null值,入队和出队的时间复杂度是O(log(n))。
D、PriorityQueue是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。ConcurrentLinkedQueue是一个基于链接节点的***线程安全队列,该队列的元素遵循FIFO原则   AC

8.关于ThreadLocal类 以下说法正确的是

A ThreadLocal继承自Thread

B ThreadLocal实现了Runnable接口

C ThreadLocal重要作用在于多线程间的数据共享

D ThreadLocal是采用哈希表的方式来为每个线程都提供一个变量的副本

E ThreadLocal保证各个线程间数据安全,每个线程的数据不会被另外线程访问和破坏

参考答案:选DE.

1、ThreadLocal的类声明: public class ThreadLocal 可以看出ThreadLocal并没有继承自Thread,也没有实现Runnable接口。所以AB都不对。

2、ThreadLocal类为每一个线程都维护了自己独有的变量拷贝。每个线程都拥有了自己独立的一个变量。 所以ThreadLocal重要作用并不在于多线程间的数据共享,而是数据的独立,C选项错。 由于每个线程在访问该变量时,读取和修改的,都是自己独有的那一份变量拷贝,不会被其他线程访问, 变量被彻底封闭在每个访问的线程中。所以E对。

3、ThreadLocal中定义了一个哈希表用于为每个线程都提供一个变量的副本:  static class ThreadLocalMap {         static class Entry extends WeakReference {             /** The value associated with this ThreadLocal. */             Object value;             Entry(ThreadLocal k, Object v) {                 super(k);                 value = v;             }         }         /**          * The table, resized as necessary.          * table.length MUST always be a power of two.          */         private Entry[] table; } 所以D对。

ThreadLocal主要作用是数据的独立,保证了并发时线程的安全性,因为每个线程都会创建一个独立的副本,它并不继承Thread类也不实现Runnable接口。DE

9.牛客练习笔记-JAVA 9/28_第2张图片

10. 在为传统面向对象语言的程序做单元测试的时候,经常用到mock对象。Mock对象通过反射数。请问反射最大程度破坏了面向对象的以下哪个特性?

A 封装

B 多态

C 继承

D 抽象

正确答案:A   你的答案:C

参考答案:A.封装 反射破坏代码的封装性,破坏原有的访问修饰符访问限制 因为反射可以绕过访问权限,访问类的私有属性和方法

mock对象:也成为伪对象,在测试中的利用mock对象来代替真实对象,方便测试的进行。

java的封装性:指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,通过该类提供的方法实现对内部信息的操作访问。

反射机制:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性

11.运用下列哪个命令能够获取JVM的内存映像

A jinfo

B jmap

C jhat

D jstat

正确答案:B

1、jps:查看本机java进程信息。

2、jstack:打印线程的信息,制作线程dump文件。

3、jmap:打印内存映射,制作dump文件

4、jstat:性能监控工具

5、jhat:内存分析工具

6、jconsole:简易的可视化控制台

7、jvisualvm:功能强大的控制台

 12.以下代码的输出结果是?

public class B
{
    public static B t1 = new B();
    public static B t2 = new B();
    {
        System.out.println("构造块");
    }
    static
    {
        System.out.println("静态块");
    }
    public static void main(String[] args)
    {
        B t = new B();
    }
}

A 静态块 构造块 构造块 构造块

B 构造块 静态块 构造块 构造块

C 构造块 构造块 静态块 构造块

D 构造块 构造块 构造块 静态块

 总结一下: 1.程序入口main方法要执行首先要加载类B 2.静态域:分为静态变量,静态方法,静态块。这里面涉及到的是静态变量和静态块,当执行到静态域时,按照静态域的顺序加载。并且静态域只在类的第一次加载时执行 3.每次new对象时,会执行一次构造块和构造方法,构造块总是在构造方法前执行(当然,第一次new时,会先执行静态域,静态域〉构造块〉构造方法) 注意:加载类时并不会调用构造块和构造方法,只有静态域会执行 4.根据前三点,首先加载类B,执行静态域的第一个静态变量,static b1=new B,输出构造块和构造方法(空)。ps:这里为什么不加载静态方法呢?因为执行了静态变量的初始化,意味着已经加载了B的静态域的一部分,这时候不能再加载另一个静态域了,否则属于重复加载 了(静态域必须当成一个整体来看待。否则加载会错乱) 于是,依次static b2 =new B,输出构造块,再执行静态块,完成对整个静态域的加载,再执行main方法,new b,输出构造块。

13.如果希望监听TCP端口9000,服务器端应该怎样创建socket?

A new Socket("localhost",9000);

B new ServerSocket(9000);

C new Socket(9000);

D new ServerSocket("localhost",9000);

正确答案:B

ServerSocket(int port) 是服务端绑定port端口,调accept()监听等待客户端连接,它返回一个连接队列中的一个socket。

Socket(InetAddress address , int port)是创建客户端连接主机的socket流,其中InetAddress是用来记录主机的类,port指定端口。

socket和servletSocket的交互如下图所示

牛客练习笔记-JAVA 9/28_第3张图片

详细了解,大家可以看此博客:http://www.cnblogs.com/rond/p/3565113.html

14.在java语言中,如果你编写一个多线程序,可以使用的方法是()

A 扩展类Thread

B 实现Runnable接口

C 扩展类 Runnable

D 实现接口Thread

正确答案:AB

Java多线程实现方式主要有四种:继承Thread类、实现Runnable接口、实现Callable接口通过FutureTask包装器来创建Thread线程、使用ExecutorService、Callable、Future实现有返回结果的多线程。

15.下面有关servlet和cgi的描述,说法错误的是?

A servlet处于服务器进程中,它通过多线程方式运行其service方法

B CGI对每个请求都产生新的进程,服务完成后就销毁

C servlet在易用性上强于cgi,它提供了大量的实用工具例程,例如自动地解析和解码HTML表单数据、读取和设置HTTP头、处理Cookie、跟踪会话状态等

D cgi在移植性上高于servlet,几乎所有的主流服务器都直接或通过插件支持cgi

 Servlet在移植性方面更高于CGI。Servlet是基于Java的标准,可以在支持Java Servlet规范的任何Web容器中运行,如Tomcat、Jetty等。而CGI是一种通用的Web服务器接口,虽然大多数主流服务器都支持CGI,但并不是所有服务器都直接支持CGI,有些服务器可能需要通过插件或配置来支持CGI。因此,从移植性的角度来看,Servlet更具优势。

收获知识点总结

1.全选,Object 类中方法及说明如下:

registerNatives()   //私有方法

getClass()    //返回此 Object 的运行类。 hashCode()    //用于获取对象的哈希值。 equals(Object obj)     //用于确认两个对象是否“相同”。 clone()    //创建并返回此对象的一个副本。 toString()   //返回该对象的字符串表示。    notify()    //唤醒在此对象监视器上等待的单个线程。    notifyAll()     //唤醒在此对象监视器上等待的所有线程。    wait(long timeout)    //在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或        者超过指定的时间量前,导致当前线程等待。    wait(long timeout, int nanos)    //在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。 wait()    //用于让当前线程失去操作权限,当前线程进入等待序列 finalize()    //当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。

2.线程的生命周期中包含五种状态:初始态、就绪态、运行态、阻塞态、死亡状态。

其状态转换如下图所示:

牛客练习笔记-JAVA 9/28_第4张图片

3.使用泛型的好处

1,类型安全。 泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有泛型,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。

2,消除强制类型转换。 泛型的一个附带好处是,消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。

3,潜在的性能收益。 泛型为较大的优化带来可能。在泛型的初始实现中,编译器将强制类型转换(没有泛型的话,程序员会指定这些强制类型转换)插入生成的字节码中。但是更多类型信息可用于编译器这一事实,为未来版本的 JVM 的优化带来可能。由于泛型的实现方式,支持泛型(几乎)不需要 JVM 或类文件更改。所有工作都在编译器中完成,编译器生成类似于没有泛型(和强制类型转换)时所写的代码,只是更能确保类型安全而已。

所以泛型只是提高了数据传输安全性,并没有改变程序运行的性能

4.CopyOnWriteArrayList的实现原理

CopyOnWriteArrayList的实现原理 
在使用CopyOnWriteArrayList之前,我们先阅读其源码了解下它是如何实现的。以下
代码是向ArrayList里添加元素,可以发现在添加的时候是需要加锁的,否则多线程写的
时候会Copy出N个副本出来。 
public boolean add(T e) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {

        Object[] elements = getArray();

        int len = elements.length;
        // 复制出新数组

        Object[] newElements = Arrays.copyOf(elements, len + 1);
        // 把新元素添加到新数组里

        newElements[len] = e;
        // 把原数组引用指向新数组

        setArray(newElements);

        return true;

    } finally {

        lock.unlock();

    }

}

final void setArray(Object[] a) {
    array = a;
}
读的时候不需要加锁,如果读的时候有多个线程正在向ArrayList添加数据,读还是
会读到旧的数据,因为写的时候不会锁住旧的ArrayList。 
public E get(int index) {
    return get(getArray(), index);
} CopyOnWriteArrayList适用于读多写少的并发场景

5.、线程的创建方式

1)继承Thread类创建线程

2)实现Runnable接口创建线程

3)使用CallableFuture创建线程

4)使用线程池创建线程

6.Servlet和CGI(Common Gateway Interface)都是用于处理Web请求的技术,但它们有一些不同之处。

Servlet是Java编写的服务器端组件,它运行在支持Java Servlet规范的Web容器中(如Tomcat)。Servlet通过继承javax.servlet.Servlet接口来实现,它可以接收HTTP请求并生成HTTP响应。Servlet可以处理动态内容、会话管理、数据库访问等功能。Servlet具有更好的性能和可扩展性,并且可以与Java EE平台的其他组件(如JSP、EJB等)进行集成。

CGI是一种通用的Web服务器接口,它允许外部程序(通常是脚本)与Web服务器进行通信。CGI程序可以用任何编程语言编写,如Perl、Python、C++等。当Web服务器接收到CGI请求时,它会将请求的数据传递给CGI程序,并将CGI程序的输出作为HTTP响应返回给客户端。CGI程序可以处理动态内容,但每个请求都需要启动一个新的进程,这可能会导致性能问题。

总结来说,Servlet是Java编写的服务器端组件,运行在Java Servlet容器中,具有更好的性能和可扩展性;而CGI是一种通用的Web服务器接口,可以用任何编程语言编写,但每个请求都需要启动一个新的进程,性能较差。

每日一记:

1、你是怎样理解OOP面向对象的

面向对象是利于语言对现实事物进行抽象。面向对象具有以下特征:

(1)继承:继承是从已有类得到继承信息创建新类的过程

(2)封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。

(3)多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。

2、你是怎样理解多态的?什么地方用过?

同一个行为具有多个不同表现形式或形态的能力。(重写和重载正是多态)

父类引用指向子类对象,例如 List list = new ArrayList();就是典型的一种多态的体现形式

3、sleep和wait在线程里有什么区别?(上海)

sleep方法:

属于Thread类中的方法;会导致程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持着,当指定时间到了之后,又会自动恢复运行状态;在调用sleep方法的过程中,线程不会释放对象锁。(只会让出CPU,不会导致锁行为的改变)

wait方法:

属于Object类中的方法;在调用wait方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify方法后本线程才进入对象锁定池准备。获取对象锁进入运行状态。(不仅让出CPU,还释放已经占有的同步资源锁

你可能感兴趣的:(牛客练习笔记-JAVA,笔记,java,开发语言)