JAVA第一阶段考试试卷

JAVA第一阶段考试试卷

第一阶段考试试卷

java

public class Test {

public static void main(String[] args) {

int a = 12, b = 20;

if (a++ == 13 && ++b == 21) {

System.out.println("ok");

}

System.out.println("a=" + a);

System.out.println("b=" + b);

}

}

13  20

 

赋值操作符:

=   例如:   int x=0,i=1,j=1;

*=  例如:   a*=b 等价于 a=a*b

/=  例如:   a/=b 等价于 a=a/b;

%=  例如:   a%=b 等价于 a=a%b;

+=        例如:   a+=b 等价于 a=a+b;

-=  例如:   a-=b 等价于 a=a-b;

其他的都是类似情况

 

a+=1; a++

特殊情况:i++ 和 ++i

i++表示先使用i的值,然后再让i自增1。

++i表示先让i的值自增1,然后再使用i的值。

例如:

int a = 1;

System.out.println(a++);//1

System.out.println(a);//2

---------------------------------

int b = 1;

System.out.println(++b);//2

System.out.println(b);//2

 

 

类似的i-- 和 --i也是一样的区别

 

逻辑操作符

短路操作符,如果能根据操作左边的布尔表达式就能推算出整个表达式的布尔值,将不执行操作符右边的布尔表达式;

 

短路与

&& 左边的布尔表达式的值为false, 整个表达式值肯定为false, 此时会忽略执行右边的布尔表达式。

false&&true

int a = 1;

int b = 2;

int c = 3;

a>b&&c>b

 

//没有短路功能

a>b&c>b

 

短路或

|| 左边的布尔表达式的值为true, 整个表达式值肯定为true, 此时会忽略执行右边的布尔表达式。

 

2. 请写出五个运行时异常(5分)

NullPointerException:

 

ClassCastException:

 

ArrayIndexOutOfBoundsException:数组越界

ArrayStoreException:

(试图将错误类型的对象存储到一个对象数组时抛出的异常)

 

ArithmeticException:

(当出现异常的运算条件时,抛出此异常。例如,一个整数“除以零”时,抛出此类的一个实例)

 

特点:不用try-catcch语句,都在java.lang.RuntimeException下面

 

3.在java中,产生一个对象的时候,最终是否一定会调用该类中的构造方法?如果不是请举例说明(4分)

不一定,当反序列化创建对象时就不会调用构造方法

 

序列化和反序列化:

Java中的序列化是指把Java对象转换为字节序列的过程

对象---序列化--->01010101

Java中的反序列化是指把字节序列恢复为Java对象的过程

01010101---反序列化--->对象

 

思考:为什么需要序列化和反序列化?

 

2)如何实现序列化和反序列化

使用对象流即可实现对象的序列化和反序列化

ObjectOutputStream类中的方法可以完成对象的序列化:

public final void writeObject(Object obj){..}

 

ObjectInputStream类中的方法可以完成对象的反序列化:

public final Object readObject(){..}

 

注:这俩个对象流都属于字节流

 

3)序列化的要求

只有实现了java.io.Serializable接口的类的对象才可以被序列化,否则序列化时会报错

 

思考:测试序列化版本号的作用是什么?

 

4)transient关键字

在对象序列化的时候,被transient修饰的属性的值,在序列化过程中是会被忽略掉的。

 

4.以下代码运行的结果为:(4分)

public class Test {

public int test() {

int a = 1;

int[] arr = {90,5,6,7};

try {

a = arr[arr.length];

return a;

} catch (Exception e) {

a = arr[0]++;

return a++;

} finally {

a = 50;

}

}

public static void main(String[] args) {

System.out.println(new Test().test());

}

}

 

90

 执行了finally里面的内容

return表示跳出整个循环返回一个值。

finally里面加一个return a 会把90给覆盖掉,变成50

数组下标越界

对于一个长度为n的数组对象,它的的下标取值范围是[0,n-1],这里的0和n-1就是这个数组对象的下标边界,使用下标的过程中不能超出这个边界。如果超出那么就会运行报错.

例如:

int[] a = new int[4];

a[4] = 10;

 

运行后结果:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4

at com.briup.test.ArrayTest.main(ArrayTest.java:7)

 

 

5.以下程序运行结果为:(2分)

public class Test {

public static void main(String[] args) {

int x = 127;

int y = 127;

Integer a = 127;

Integer b = 127;

System.out.println(x == y);

System.out.println(a == b);

}}

true,true

       包装类中存储了:-128~127的地址值(byte范围),所以输出true,超过此范围则表示的对象内存地址值不同,输出false。

包装类(Wrapper) Integer

在java中,有八种基本的数据类,这八种类型所表示的数据只是一些简单的数值(8/16/32/64位的数字),它们都不是对象,所以在API又针对这八种类型提供了对于的类类型,也就是包装类型,它们分别是:

 

    Primitive-Type                 Wrapper-Class

byte                        Byte

short                        Short

int                        Integer

long                        Long

float                        Float

double                        Double

boolean                Boolean

char                        Character

 

1)这些对应的包装类型都是java.lang下的类

在代码中可以直接使用而不需要导入.

 

2)每种包装类中都定义属性和方法供其对象使用

这是从基本类型变为包装类型最明显的区别,现在指向的是对象了,可以访问对象中的属性和调用对象中的方法了,之前只是一个简单的数值,没有任何属性和方法。

例如:

//使用变量i不能访问任何属性和访问

//因为变量i没有指向对象,也不能指向对象

int i = 1;

 

//查看API可知Integer类中的构造器如果使用

//使用变量i可以访问Integer类中定义的属性和方法

//因为变量i指向的是对象,这是一个引用类型的变量

Integer i = new Integer(1);

或者

Integer i = new Integer("1");

 

注:包装类中的属性和方法大都是静态的,可以使用类名直接访问。(也有非静态的方法,就需要使用对象调用了)

 

例如:

main:

System.out.println(Integer.MAX_VALUE);

System.out.println(Integer.MIN_VALUE);

System.out.println(Integer.toBinaryString(100));

 

3)JDK1.5增加了自动拆箱装箱的功能(低版本JDK中编译报错)

注:针对八种基本类型及其包装类型,这里以int和Integer为例

 

//自动装箱,把字面值1包装成Integer类型对象

Integer i1 = 1;

 

//自动拆箱,把Integer对象转变为一个简单的int类型值

int i2 = new Integer(1);

 

注:

//编译通过

Integer a = 1;

 

//编译报错

//1可以自动装箱为Integer类型对象

//但是Integer和Long没有任何关系

Long b = 1;

 

//因为int是32位 long是64位

int --可以自动转换为--> long

 

//因为Integer和Long没有子父类关系

Integer --不能转换为--> Long

 

基本数据类型又可以分为:整型 浮点类型 布尔类型 字符类型

整型

byte                8位        1字节

short                16位        2字节

int                32位        4字节

long                64位        8字节

 

浮点类型

float                32位        4字节

double                64位        8字节

 

布尔类型

boolean        8位        1字节

 

字符类型

char                16位        2字节

 

注意:java中采用unicode编码,用俩个字节表示一个字符,但是在其他字符编码中可能不是使用俩个字节表示一个字符

 

 

==和equals方法的区别

这俩个都是对俩个变量做比较的。

1)基本类型变量的比较

基本类型变量指向的不是对象,不能调用方法,所以只能使用==进行比较,并且比较的是基本类型变量的简单数值是否相等。

 

2)引用类型变量的比较

引用类型变量指向的是对象,所以既可以使用==进行比较,也可以使用equals进行比较

 

区别在于:

equals是Object中的方法,每个对象都可以调用和其他对象比较是否相等,默认比较的是俩个引用所指向的对象内存地址值(和==号的作用一样),但是也可以在类中对equals方法进行重写,按照自己的逻辑来比较俩个对象。

 

==是java中的基本的操作符,是不能重写的,俩个引用使用==进行比较,那么比较的是引用所指向的内存地址值是否相同。

 

6.方法的重载的要求是什么?方法的重写中,对方法的访问修饰符和抛出异常分别有什么要求?(5分)

方法重载要求参数列表不同,并且只能发生在本类种,重写的方法的访问修饰符只能大或者同级,抛出的异常只能同级或者比原来的异常范围小

 

方法重载

类中有多个方法,有着相同的方法名,但是方法的参数各不相同,这种情况被称为方法的重载。

方法的重载可以提供方法调用的灵活性。

 

例如:System.out.println()中的println方法,为什么可以把不同类型的参数传给这个方法?

 

例如:

public class Test{

public void test(String str){

 

}

 

public void test(int a){

}

}

 

 

方法重载必须满足一下条件:

1)方法名相同

2)参数列表不同(参数的类型、个数、顺序的不同)

public void test(Strig str){}

public void test(int a){}

 

public void test(Strig str,double d){}

public void test(Strig str){}

 

public void test(Strig str,double d){}

public void test(double d,Strig str){}

3)方法的返回值可以不同

 

注:在java中,判断一个类中的俩个方法是否相同,主要参考俩个方面:方法名字和参数列表

 

方法重写(方法覆盖)

1)方法重写只存在于子类和父类(包括直接父类和间接父类)之间。在同一个类中方法只能被重载,不能被重写.

 

    2)静态方法不能重写

       a. 父类的静态方法不能被子类重写为非静态方法 //编译出错

       b. 父类的非静态方法不能被子类重写为静态方法;//编译出错

       c. 子类可以定义与父类的静态方法同名的静态方法(但是这个不是覆盖)

例如:

 A类继承B类 A和B中都一个相同的静态方法test

 B a = new A();

 a.test();//调用到的时候B类中的静态方法test

 

 A a = new A();

 a.test();//调用到的时候A类中的静态方法test

 

     可以看出静态方法的调用只和变量声明的类型相关

 这个和非静态方法的重写之后的效果完全不同

 

    3)私有方法不能被子类重写

子类继承父类后,是不能直接访问父类中的私有方法的,那么就更谈不上重写了。

 

例如:

public class Person{

private void run(){}

}

//编译通过,但这不是重写,只是俩个类中分别有自己的私有方法

public class Student extends Person{

private void run(){}

}

 

 

    4)重写的语法

1.方法名必须相同

2.参数列表必须相同

3.访问控制修饰符可以被扩大,但是不能被缩小

public protected default private

4.抛出异常类型的范围可以被缩小,但是不能被扩大

ClassNotFoundException ---> Exception 

5.返回类型可以相同,也可以不同,如果不同的话,子类重写后的方法返回类型必须是父类方法返回类型的子类型

例如:父类方法的返回类型是Person,子类重写后的返回类可以是Person也可以是Person的子类型

 

注:一般情况下,重写的方法会和父类中的方法的声明完全保持一致,只有方法的实现不同。(也就是大括号中代码不一样)

 

例如:

public class Person{

public void run(){}

 

protected Object test()throws Exception{

return null;

}

}

//编译通过,子类继承父类,重写了run和test方法.

public class Student extends Person{

public void run(){}

 

public String test(){

return "";

}

}

 

 

    5)为什么要重写

子类继承父类,继承了父类中的方法,但是父类中的方法并不一定能满足子类中的功能需要,所以子类中需要把方法进行重写。

 

7.请写出Java中的基本数据类型和引用数据类型分别有哪些?,并指出基本数据类型的变量 和 引用数据类型的变量,俩者的核心区别是什么?(4分)

基本数据类型:byte short int long float double char boolean 

引用数据类型:类类型 接口 数组

基本数据类型变量直接存储在栈上;引用数据类型变量,首先要在栈上给其引用分配一块内存,而对象的具体信息都存储在堆内存上,然后由栈上面的引用指向堆中对象的地址

 

8.假如T1线程和T2线程出现了死锁的状况,那么请说明该状态下,线程和锁的持有情况。(5分)

有两个锁,T1线程锁住第一个,T2线程锁住了第二个,同时T1试图锁第二个,失败,因为T2已经锁住了,T1只能等待.就在这时T2试图锁第一个,结果失败,因为T1已经锁住了,T2只好等待

 

9.以下代码运行是否有错,如果没有报错,结果是什么?,如果报错应该怎么改?(2分)

 

class Person {

 

}

public class Test {

public static void main(String[] args) throws IOException, Exception {

List<Person> persons = new ArrayList<>();

persons.add(new Person());

persons.add(new Person());

persons.add(new Person());

persons.add(new Person());

 

FileOutputStream fos = new FileOutputStream("src/obj.txt");

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(persons);

oos.flush();

oos.close();

         System.out.println(“保存成功”)

}

}

 

报错,当容器被序列化时,容器里面的数据也要被序列化。因此需要将Person类实现序列化接口。

class Person implements Serializable {

}

 

*10. 类A中有非静态方法x,类B中有非静态方法y,请问在x方法和y方法上直接使用synchronized关键字分别修饰这俩个方法,那么在多线程环境下,这个俩个方法x和y,是否可以实现线程同步的效果?如果不可以,请说明原因,并简单说明如果修改可以让它们实现线程同步的效果?(4分)

不可以,当synchronized修饰非静态方法时,锁对象为this,因此不可以实现同步,将同步方法换成同步代码块并且使用同一个锁对象

 

    线程同步的实现

在java中,使用synchronized关键字来实现线程同步的效果。

synchronized关键字可以用来修饰方法,也可以直接作用到某段代码上

 

例如:

public class Test{

private int x;

public synchronized void test(){

String name = Thread.currentThread().getName();

for(int i=0;i<100;i++){

x++;

}

System.out.println(name+": x="+x);

}

}

 

 

例如:

public class Test{

private int x;

public void test(){

String name = Thread.currentThread().getName();

synchronized(this){

for(int i=0;i<100;i++){

x++;

}

}

System.out.println(name+": x="+x);

}

}

 

 

 

synchronized关键字是加锁的意思,用它来修饰方法就表示给该方法加了锁,从而达到线程同步的效果;用它来修饰代码块就表示给该代码块加了锁,从而达到线程同步的效果。

 

例如:一个方法test使用synchronized关键字修饰后加了锁,如果这个时候有俩个线程对象t1和t2要并发访问test方法,假设t1先抢到了CPU的执行权,从而率先拿到了test方法上的锁,然后就进到test方法中执行代码,一个时间片用完之后,就退回到就绪状态,但是t1线程却依然拿着锁,那么下次CPU的抢占即使是t2抢到了也没有办法执行test方法,因为t2拿不到锁就没有办法进到test方法中执行代码,这时候t2线程就会进入到锁池里面了。

 

注:java中任何对象都可以当做锁,能否拿到锁就决定了一个线程是否能进入到被锁的代码块中去执行代码

 

 

例如:

public class Test{

//默认使用this来充当这把锁,锁的是test1方法

public synchronized void test1(){

//代码

}

//默认使用this.getClass()来充当这把锁,锁的是test2方法

public static synchronized void test2(){

//代码

}

 

public void test3(){

//这种形式可以使用任意对象充当锁,锁的是这个代码块

synchronized(任意对象){

//代码

}

}

}

 

 

11. byte类型的数字的最小值和最大值分别是多少?如果把数字-8进行先取反(~)然后再加1,那么结果打印出来是多少?(3分)

最小值 -128,最大值 127    8

 

12. java中的io流中,InputStream类是字节输入流中的父类型,类中有我们常用的非常重要的方法read,请说明一下三个read方法的作用:(3分)

int read();

int read(byte[] buf);

int read(byte[] buf,int a,int b);

  read();

 从输入流中读取数据的下一个字节。返回 0 到 255 范围内的 int 字节,

返回读取得字节

 read(byte[] buf);

从输入流中读取一定数量的字节,并将其存储在缓冲区数组 buf中。返回读取得字节数量。

 read(byte[] buf,int a,int b)

将输入流中最多 len 个数据字节读入 byte 数组。尝试读取 len 个字节,但读取的字节也可能小于该值。以整数形式返回实际读取的字节数

 

13. 拥有静态成员的内部类一定是静态内部类吗,如果不是,请举例说明。(2分)

拥有静态成员的内部类一定是静态内部类

 

14.以下代码是否会编译报错,如果报错请指出哪一行代码报错,并说明理由。(2分)

public static void main(String[] args) {

short a = 1; // 第一行

a += 1;     // 第二行

a = a + 1; // 第三行

}

a += 1;隐式强制转换

第三行代码编译报错,在运算时会先将a自动转成int类型,两个int类型数据相加结果还是为int,然后将int类型数据赋给short类型就会编译报错。

 

类型转换

1)基本类型之间的转换

隐式转换(自动转换)

byte a = 1;

//a是byte类型(8位),b是int类型的(32)

//编译通过,类型自动转换(隐式转换)

int b = a;

 

特点:小的可以自动转换(隐式转换)为大的,因为无非就是在前面多补几个0而已,不会影响数据值

 

显式转换

//编译报错,32位的值给8位的变量

int a = 100;

byte b = a;

 

//编译通过

//这时候需要类型强制转换(俗称强转,也就是显式转换)

int a = 100;

byte b = (byte)a;

            0100 0000 0000 0000

                      0000 0000

特点:大的值给小的变量,需要强制转换,但是转换后的结果JVM不会保证还是正确的,因为这是程序员自己的个人行为.

 

 

2)引用类型之间的转换

隐式转换

//编译通过,类型自动转换(隐式转换)

Student s = new Student();

Object o = s;

 

特点:子类类型的变量可以自动转换(隐式转换)为父类类型

 

显式转换

//编译通过,运行后也不报错

//因为引用o本来指向的就是Student对象

Object o = new Student();

Student s = (Student)o;

 

//编译通过,运行后报错

//因为o本来指向的时候Teacher对象

//而Teacher类型对象和Student类型没有任何关系

Object o = new Teacher();

Student s = (Student)o;

 

 

15.请描述List集合、Set集合、Map集合的特点,Map集合中entrySet方法的返回值是什么?(4分)

List集合能够存放有序可重复的数据

Set集合存放无序不可重复的数据

Map集合一次能够存两列数据,并且key不可重复

Map集合中 entrySet返回的是Entry的Set集合(写键值对的Set集合也可以)。

 

List接口和Set接口

List和Set都是Collection接口的子接口,但它们各自的特点不同。

 

List类型集合特点:集合中的元素有序且可重复

Set类型集合特点 :集合中的元素不可重复,有没有序要看Set接口具体的实现类是谁。

 

注:有序指的是元素放到集合中的顺序和循环遍历出来的顺序一致

 

List接口常见的实现类有:ArrayList、LinkedList、Vector等

1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构

2.对于数据的随机访问,ArrayList效率优于LinkedList,因为LinkedList要移动指针

3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据

4.Vector是线程安全的集合,但是速度慢

5.查看API可知,List接口中是这些集合中共有的方法,而且每个集合类中又有一些自己独有的方法。

 

Set接口常见的实现类有:HashSet、LinkedHashSet

HashSet集合中元素的特点 :无序不可重复

LinkedHashSet集合中元素的特点:有序不可重复

 

Map接口

Map类型的集合与Collection类型的集合不同,Map类型的集合存储数据的时候,要使用Key-Value的形式(键值对),且Key值不能重复,否则会覆盖原来的键值对

 

Map接口中的一些方法

put                        方法

get                        方法

clear                        方法

containsKey                方法

containsValue                      方法

isEmpty                        方法

size                        方法

remove                        方法

 

Map接口的常用实现类

HashMap类和Hashtable类

1.HashMap是线程不安全的,Hashtable是线程安全的

2.HashMap允许key值或者value值为null,但是Hashtable中的key值或者value值都不允许为null,否则报错.

 

注:map中的key和value都必须是Object

 

Map类型集合的遍历

1.使用keySet方法,可以返回该Map集合中的所有key值的set类型集合

例如:

Map map = new HashMap();

//调用put方法存值

 

for(Object key:map.keySet()){

System.out.println(key+" : "+map.get(key));

}

 

2.使用values方法,可以返回该Map集合中所有value值的Collection类型集合

例如:

Map map = new HashMap();

//调用put方法存值

 

for(Object value:map.values()){

System.out.println(value);

}

 

3.使用entrySet方法,可以返回该Map集合中,包含所有Entry类型对象的Set集合

Set<Map.Entry<K,V>> entrySet();

注:Entry是声明Map接口中的内部接口(看API或源码可知),一个Entry类型对象就表示Map中的一组键值对(K-V)

 

例如:

Map map = new HashMap();

//调用put方法存值

 

Set entrySet = map.entrySet();

for(Object obj:entrySet){

Entry entry = (Entry)obj;

System.out.println(entry.getKey());

System.out.println(entry.getValue());

}

 

注意这里导入Entry接口的形式。

 

SortedMap接口和TreeMap类

SortedMap接口是Map的子接口,其进一步提供对于键的排序功能。

TreeMap类就是SortedMap接口的实现类。

 

TreeMap可以对key值进行自然排序或者比较器排序,其用法和TreeSet是一致的。

 

*16.请问以下代码无论运行多少次一定是 ”test11..”打印在前,”test22..”打印在后吗,如果是请说明原因,如果不是也请说明原因。(3分)

 

public static void main(String[] args) {

Thread t1 = new Thread() {

@Override

public void run() {

System.out.println("test11..");

}

};

Thread t2 = new Thread() {

@Override

public void run() {

System.out.println("test22..");

}

};

t1.run();

t2.run();

}

是的,因为没有启动线程,而是调用了线程里面得run方法,属于方法的调用是单线程,不是多线程。

 

17.请问可以调用某些特定的方法让jvm强制性的进行垃圾回收吗,如果可以请说明理由,不可以也请说明理由。(2分)

不可以,java开发人员可以调用特定的方法请求jvm去进行垃圾回收,具体回不回收还是由jvm去决定

 

18.抽象方法是否可以为静态的,如果可以直接写可以,如果不可以请说明理由。(2分)

不可以,因为如果可以,那么就可以通过类名去调用,而抽象方法没有方法体无法去执行该抽象方法 。或者 抽象方法就是用来被子类重写的,而静态方法不能够被重写,所以冲突。

 

19.请写出获取一个类类型的Class对象的几种方式?基本数据类型是否可以获取其Class对象,如果不可以直接写不可以,如果可以,请举例说明。(4分)

Class.forName(“全类名”);

类名.class

对象名.getClass();

基本数据类型可以获取Class对象,方式为: 基本数据类型.class

 

*20. Java中的泛型的上限和下限是什么意思,请使用List接口声明局部变量的方式,来举例说明该问题(4分)

向下限定:

List<? extends Object> list = new ArrayList<>();

泛型只能为 Object或者Object的子类

向上限:

List<? super String> list = new ArrayList<>();

泛型只能为:String以及String的父类

 

21. 抽象类与接口的区别是什么?抽象类与接口是否都有构造器,为什么?(4分)

抽象类:

抽象类中可以拥有抽象方法也可以拥有非抽象方法

抽象类中可以拥有普通变量也可以拥有常量

抽象类中可以拥有着自己的构造器

接口:

接口里面所有得方法都是抽象方法

        接口里面所有得变量都是静态常量

接口没有构造器

抽象类有构造器,接口没有,因为类与类是继承关系,当创建子类对象时会调用父类中的构造器。而类与接口是实现关系,当创建该类对象时会调用该类的父类的构造器。

 

22. 请对以下数组进行扩容,请写出代码(写出一种方式即可)(3分)

int[] arr = {1,2,3,5};

int[] arr = {1,2,3,5};

int[] obj = new int[arr.length * 2 + 1];

System.arraycopy(arr, 0, obj, 0, arr.length);

arr = obj;

 

*23. 以下代码执行结果为?(3分)

class A {

public A() {

System.out.println(getName());//已经被子类重写l

}

public String getName() {

return "lisi";

}

}

public class Test extends A {

public Test() {

System.out.println(getName());

}

public String getName() {

return "wangwu";

}

public static void main(String[] args) {

new Test();

}

}

wangwu  wangwu

 

24. int a = 15;

   int b = 3;

怎么能把变量a和变量b的值进行交换?(要求不使用第三个变量,至少写出【俩种】方案)(4分)

第一种:

a = a ^ b;

b = a ^ b;

 a = a ^ b;

第二种:

    a = a + b;

 b = a - b;

 a = a – b;

 

 

*25.假设现在我们登录unix服务器后所处的位置在  /home/tom(4分)

  /home/tom目录下有来个子目录:

/home/tom/src

/home/tom/bin

  我们在当前/home/tom下使用vi命令分别编写俩个java源文件

  vi src/Student.java

  vi src/StudentTest.java

  在StudentTest.java中的主函数中测试Student类中的某个方法,这俩个类都是com.test包下面的类

  那么现在我们要如何用命令去*编译*这俩个类并且*运行*StudentTest类中的主函数?

  要求:这俩个类要一个一个编译,最后再运行StudentTest类的主函数,并且编译好的东西放到bin下面

 

javac -d ./bin ./src/Student.java

*javac -d ./bin -classpath ./bin/ ./src/StudentTest.java

java -cp ./bin com.test.StudentTest

 

*26.有以下代码(3分)

 

public void test()throws Exception{

synchronized (getClass()) {

for(int i=0;i<100;i++){

if(i==10){

wait();

}

}

}

}

代码编译运行的结果是什么?为什么?

运行抛出异常

锁对象为字节码对象,而wait()方法的调用是this

 

27. 下列程序在1处是否会有异常,如果没有,输出是什么?是否会运行到2处,如果会,输出是什么?为什么会有这样的结果?(3分)

public class TestClass {

public static void main(String args[]) {

List list = new ArrayList();

test2(list);

System.out.println(list.size()); // 1

test3(list);

System.out.println(list.size()); // 2

}

public static void test2(List list) {

list = null;

}

public static void test3(List list) {

list.add("aaaa");

}

}

 

1处没有异常,输出结果为0

可以运行到2处,结果为1

*(为什么得出这个结论?)因为方法的传递为引用传递,传递的是地址,对地址操作就是对堆里面的内存进行操作

 

28. 定义一个类Person,将多个Person对象存入TresSet中,此时有几种方式可以对集合中的对象进行排序?如果是把这些对象存放到List集合中,又该如何排序?(5分)

将Person存入TreeSet排序有两种方式:

List本身是有序的,按照放入先后顺序去进行排序

 

TreeSet类的排序功能

注:TreeSet排序永远都是从小到大排,但是谁大谁小是我们的方法说了算的

1.自然排序

核心:让元素自身具备比较性,需要实现Comparable接口,重写其compareTo方法,比较出大小后即可进行排序

java.lang.Comparable接口

例如:

public class Student implements Comparable{

private long id;

public long getId() {

return id;

}

public void setId(long id) {

this.id = id;

}

public int compareTo(Object o) {

Student s = (Student)o;

if(this.id<s.id){

return -1;

}

else if(this.id>s.id){

return 1;

}

return 0;

}

}

 

注:

s1.compareTo(s2);

返回正数说明s1大

返回负数说明s1小

返回0说明s1和s2相等

 

2.比较器排序(定制排序、客户化排序)

核心:使用比较器进行元素之间的比较,比较出大小后即可进行排序。

java.util.Comparator接口

例如:

main:

Set set = new TreeSet(new Comparator() {

@Override

public int compare(Object o1, Object o2) {

Student s1 = (Student) o1;

Student s2 = (Student) o2;

return (int)(s1.getId()-s2.getId());

}

});

 

 

注:比较器排序的优先级比自然排序的高

 

29. 网络编程中(TCP),一般情况下,如何在客户端中连接服务器端,如何知道当前是否连接成功?(2分)

在客户端创建sokcet对象并且指定ip与端口

只要服务端正常执行完 accpect()方法,就代表经历过了三次握手,客户端与服务端连接成功

 

*30. 有以下代码(5分)

public interface Test{

<T> T t(T t);//代码1

}

解释代码1的含义。

泛型标识符为T,返回值为泛型T, 方法名为 t,形参的数据类型为泛型T,形参名为t

  • 第一种是自然排序,实现Comparable
  • 第二种是在创建TreeSet时传入一个比较器
  • 运行下面代码输出结果是: (4分)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值