目录
精选牛客网鄙视题&详解(二)
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修饰