精选牛客网鄙视题&详解(二)【Java部分】

精选牛客网鄙视题&详解(二)

1. Java数组的使用

// 1.直接赋值
String arr[] = { "hello", "world", "DO", "You", "Love", "Me"};
// 2.通过new关键字
String arr1[] = new String[5];
String[] arr2 = new String[5];
// 3.初始化的同时赋值
String[] arr3 = new String[] {"hello", "world", "DO", "You", "Love", "Me"};
// 3.先定义一个数组
String[] arr4 = null;
// 赋值数组的第一个值
arr[0] = "a";

2. 原码、反码、补码

  • 源码:一个正数,按照绝对值大小转换成的二进制数;一个负数按照绝对值大小转换成的二进制数,然后最高位补1,称为原码。

  • 反码:正数的反码与原码相同,负数的反码为对该数的原码除符号位外各位取反。

  • 补码:正数的补码与原码相同,负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1.

    补充:Java中的
    >>是无符号右移,如果该数为正,则高位补0,若为负数,则高位补1;
    >>>是无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0。

3. 关于Java枚举的使用

enum AccountType
{
    SAVING, FIXED, CURRENT;
    private AccountType()
    {
        System.out.println(“It is a account type”);
    }
}
class EnumOne
{
    public static void main(String[]args)
    {
        System.out.println(AccountType.FIXED);
    }
}

// 执行结果
It is a account type
It is a account type
It is a account type
FIXED

/*
枚举类有三个实例,故调用三次构造方法,打印三次It is a account type

枚举类在后台实现时,实际上是转化为一个继承了java.lang.Enum类的实体类,原先的枚举类型变成对应的实体类型,上例中AccountType变成了个class AccountType,并且会生成一个新的构造函数,若原来有构造函数,则在此基础上添加两个参数,生成新的构造函数,如上例子中:
	private AccountType(){ System.out.println(“It is a account type”); }
会变成:
	private AccountType(String s, int i){
   		super(s,i); System.out.println(“It is a account type”); 
    }
    
而在这个类中,会添加若干字段来代表具体的枚举类型:
    public static final AccountType SAVING;
    public static final AccountType FIXED;
    public static final AccountType CURRENT;

而且还会添加一段static代码段:
    static{
        SAVING = new AccountType("SAVING", 0);
        FIXED = new AccountType("FIXED", 0);
        CURRENT = new AccountType("CURRENT", 0);
        
        $VALUES = new AccountType[]{
             SAVING, FIXED, CURRENT
        } 
    }
以此来初始化枚举中的每个具体类型。(并将所有具体类型放到一个$VALUE数组中,以便用序号访问具体类型)
在初始化过程中new AccountType构造函数被调用了三次,所以Enum中定义的构造函数中的打印代码被执行了3遍。
*/
 

4. 关于Java的垃圾回收机制

  • java提供了一个系统级的线程,即垃圾回收器线程。用来对每一个分配出去的内存空间进行跟踪。当JVM空闲时,自动回收每块可能被回收的内存,GC是完全自动的,不能被强制执行。程序员最多只能用System.gc()来建议执行垃圾回收器回收内存,但是具体的回收时间,是不可知的。
  • 当对象的引用变量被赋值为null,可能被当成垃圾。

5. 关于多线程是否释放锁资源问题

  • 鄙视题

    下列哪些操作会使线程释放锁资源?  
    A.sleep()
    B.wait()
    C.join()
    D.yield()
    
    //正确答案: B C 
    
  • sleep()方法
    在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”。不推荐使用。
    sleep()使当前线程进入阻塞状态,在指定时间内不会执行。

  • wait()方法
    在其他线程调用对象的notify或notifyAll方法前,导致当前线程等待。线程会释放掉它所占有的“锁标志”,从而使别的线程有机会抢占该锁。
    当前线程必须拥有当前对象锁。如果当前线程不是此锁的拥有者,会抛出IllegalMonitorStateException异常。
    唤醒当前对象锁的等待线程使用notify或notifyAll方法,也必须拥有相同的对象锁,否则也会抛出IllegalMonitorStateException异常。
    waite()和notify()必须在synchronized函数或synchronized block中进行调用。如果在non-synchronized函数或non-synchronized block中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常。

  • yield方法
    暂停当前正在执行的线程对象。
    yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。
    yield()只能使同优先级或更高优先级的线程有执行的机会。

  • join方法
    join()等待该线程终止。
    等待调用join方法的线程结束,再继续执行。如:t.join();//主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测

6. 关于Java中字符串的比较

  • 鄙视题

    以下程序执行的结果是()
    public class Test {
        private String name = "abc";
        public static void main(String[] args) {
            Test test = new Test();
            Test testB = new Test();
            String result = test.equals(testB) + ",";
            result += test.name.equals(testB.name) + ",";
            result += test.name == testB.name;
            System.out.println(result);
        }
    }
    
    // 执行结果
    false,true,true
    
  • 参考文章

7. 字节流和字符流

下面的类哪些可以处理Unicode字符?

A.InputStreamReader
B.BufferedReader
C.Writer
D.PipedInputStream

//正确答案: A B C 

/*
简单地说,字符流是字节流根据字节流所要求的编码集解析获得的
可以理解为字符流=字节流+编码集
所以本题中和字符流有关的类都拥有操作编码集(unicode)的能力。
后缀是Stream的都是字节流,其他的都是字符流。

字节流:
InputStream  
|-- FileInputStream (基本文件流)  
|-- BufferedInputStream  
|-- DataInputStream  
|-- ObjectInputStream
字符流
Reader 
|-- InputStreamReader (byte->char 桥梁) 
|-- BufferedReader (常用) 
Writer 
|-- OutputStreamWriter (char->byte 桥梁) 
|-- BufferedWriter 
|-- PrintWriter (常用)
*/

8. Java多线程中的wait()、notify()、notifyAll()、await()、signal()、signalAll()

以下哪几种方式可用来实现线程间通知和唤醒:( )
A.Object.wait/notify/notifyAll
B.ReentrantLock.wait/notify/notifyAll
C.Condition.await/signal/signalAll
D.Thread.wait/notify/notifyAll

//正确答案: A C 

/*
解析:
wait()、notify()和notifyAll()是 Object类 中的方法 ;
Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、 notify(),使用Condition1的await()、signal()这种方式实现线程间协作更加安全和高效。
*/

9. Java的 native 关键字

  • native 关键字是JNI的一部分

  • JNI是Java Native Interface的 缩写。从Java 1.1开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计 的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。

  • 使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的,比如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少保证本地代码能工作在任何Java 虚拟机实现下。

  • 使用方法

    public class HelloWorld {
        public native void displayHelloWorld();
        static {
            System.loadLibrary("hello");
        }
        public static void main(String[] args) {
            new HelloWorld().displayHelloWorld();
        }
    }
    
  • 声明native方法:如果你想将一个方法做为一个本地方法的话,那么你就必须声明改方法为native的,并且不能实现。其中方法的参数和返回值在后面讲述。

  • Load 动态库:System.loadLibrary(“hello”);加载动态库(我们可以这样理解:我们的方法displayHelloWorld()没 有实现,但是我们在下面就直接使用了,所以必须在使用之前对它进行初始化)这里一般是以static块进行加载的。同时需要注意的是 System.loadLibrary();的参数“hello”是动态库的名字。

10、关于Java中 外部类、成员内部类、局部内部类的访问修饰符问题

  • 1.类指外部类,最大的类,修饰符有public(表示该类在项目所有类中可以被导入),default(该类只能在同一个package中使用),abstract,final
  • 2.内部类指位于类内部但不包括位于块、构造器、方法内,且有名称的类,修饰符有public,private,protected访问控制符,也可以用static,final关键字修饰,public和private比较简单,一个表示所有可以被所有类访问,一个表示只能被自身访问,protected修饰的成员类可以被同一个包中的类和子类访问。而default修饰的成员类只能被同一个包中的类访问。
  • 3.局部内部类指位于块、构造器、方法内的有名称类,最多只能有final修饰
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章