笔试面试题总结(二)---软件开发

1.PreparedStatement与Statement

(1)PreparedStatement接口继承Statement, PreparedStatement 实例包含已编译的 SQL 语句,所以其执行速度要快于 Statement 对象。

(2)作为 Statement 的子类,PreparedStatement继承了 Statement 的所有功能。三种方法execute、 executeQuery 和 executeUpdate 已被更改以使之不再需要参数

(3)在JDBC应用中,如果你已经是稍有水平开发者,你就应该始终以PreparedStatement代替Statement.也就是说,在任何时候都不要使用Statement.

 

2.语句:char foo='中',是否正确?(假设源文件以GB2312编码存储,并且以javac – encoding GB2312命令编译)

这在java中是正确的,在C语言中是错误的,java的char类型占两个字节,默认使用GBK编码存储。这种写法是正确的,此外java还可以用中文做变量名。

 

3. java中的equal和==

 实例:
  
String str1 = new String("str");
String str2 = newString("str");
System.out.println("==比较 :"+ (str1 == str2));
System.out.println("equal比较:"+ str1.equals(str2));
String str3 ="str1";
String str4 ="str1";
System.out.println("==比较 :"+ (str3 == str4));
System.out.println("equal比较:"+ str3.equals(str4));

输出结果:

false
equal比较:true
true
equal比较:true

根据打印的结果可以发现使用equal比较时无论是使用自动装箱来实例化还是用new来实例化,返回的都true,而用==则不一样了,自动装箱来实例化的返回的是true,而用new来实例化的返回的确实false;先不急着解决为什么,先来了解下equals和==的区别,到时候就可以知道答案了:

equals方法最初是在所有类的基类Object中进行定义的,源码是

 
  
 public boolean equals(Object obj) 
{
    return (this == obj);
 }

可以看出这里定义的equals与==是等效的,但上面的怎么还会不一样呢?

原因就是String类对equals进行了重写:

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = count;
        if (n == anotherString.count) {
        char v1[] = value;
        char v2[] = anotherString.value;
        int i = offset;
        int j = anotherString.offset;
        while (n-- != 0) {
            if (v1[i++] != v2[j++])
            return false;
        }
        return true;
        }
    }
    return false;
    }


这里对equals重新需要注意五点:

 1)自反性:对任意引用值X,x.equals(x)的返回值一定为true. 
 2)对称性:对于任何引用值x,y,当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值一定为true; 
 3)传递性:如果x.equals(y)=true,y.equals(z)=true,则x.equals(z)=true 
 4)一致性:如果参与比较的对象没任何改变,则对象比较的结果也不应该有任何改变 
 5)非空性:任何非空的引用值X,x.equals(null)的返回值一定为false 

经过重写后就跟==有本质的区别了:

equal:是用来比较两个对象内部的内容是否相等的,由于所有的类都是继承自java.lang.Object类的,所以如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equal方法返回的却是==的判断,因此,如果在没有进行该方法的覆盖后,调用该方法是没有任何意义的。

==可用于基本类型和引用类型:当用于基本类型时候,是比较值是否相同;当用于引用类型的时候,是比较对象是否相同。

4. 关于抽象类与接口

  含有abstract修饰符的class即为抽象类,abstract类不能创建的实例对象。含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必是抽象的。abstract class类中定义抽象方法必须在具体(Concrete)子类中实现,所以,不能有抽象构造方法或抽象静态方法。如果子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为abstract类型。

接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。

下面比较一下两者的语法区别:

1).抽象类可以有构造方法,接口中不能有构造方法。

2).抽象类中可以有普通成员变量,接口中没有普通成员变量

3).抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。

4). 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。

5). 抽象类中可以包含静态方法,接口中不能包含静态方法

6). 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。

7). 一个类可以实现多个接口,但只能继承一个抽象类。二者在应用方面也有一定的区别:接口更多的是在系统架构设计方法发挥作用,主要用于定义模块之间的通信契约。而抽象类在代码实现方面发挥作用,可以实现代码的重用,例如,模板方法设计模式是抽象类的一个典型应用,假设某个项目的所有Servlet类都要用相同的方式进行权限判断、记录访问日志和处理异常,那么就可以定义一个抽象的基类,让所有的Servlet都继承这个抽象基类,在抽象基类的service方法中完成权限判断、记录访问日志和处理异常的代码,在各个子类中只是完成各自的业务逻辑代码。

 

5. super和this的异同:

1)super(参数):调用基类中的某一个构造函数(应该为构造函数中的第一条语句) 

2)this(参数):调用本类中另一种形成的构造函数(应该为构造函数中的第一条语句)
3)super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名    super.成员函数据名(实参)

4)this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)

5)调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。

6)super()和this()类似,区别是,super()从子类中调用父类的构造方法,this()在同一类内调用其它方法。

7)super()和this()均需放在构造方法内第一行。

8)尽管可以用this调用一个构造器,但却不能调用两个。

9)this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。

10)this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。

 

6. JAVA语言的下面几种数组复制方法中,哪个效率最高?

A.for循环逐一复制
B.System.arraycopy
C.System.copyof
D.使用clone方法

解析:

 A、for循环的话,很灵活,但是代码不够简洁.

 B、System.arraycopy()源码。可以看到是native方法:native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。 可以将native方法比作Java程序同C程序的接口。

public static native void arraycopy(Object src,int srcPos,Object dest,int destPos,int length);
  public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)       
 从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。从 src 引用的源数组到 dest 引用的目标数组,数组组件的一个子序列被复制下来。被复制的组件的编号等于 length 参数。源数组中位置在 srcPos 到 srcPos+length-1 之间的组件被分别复制到目标数组中的 destPos 到 destPos+length-1 位置。

 C、选项有误,copyOf不是System的方法,而是Arrays的方法,下面是源码,可以看到本质上是调用的arraycopy方法。,那么其效率必然是比不上 arraycopy的

public static int[] copyOf(int[] original, int newLength) {
   int[] copy = new int[newLength];
   System.arraycopy(original, 0, copy, 0,
   Math.min(original.length, newLength));
   return copy;
}

 D。clone的话,返回的是Object,需要强制转换。 一般用clone效率是最差的,

注:arraycopy是个native方法,测试结果表明, 当数组很小,但内存是调用次数多的话。使用它复制数组并不比for循环手工复制数组快。 但是如果是数组比较大,那么使用System.arraycopy会比较有优势,因为其使用的是内存复制省去了大量的数组寻址访问等时间。 

native方法: 
Java不是完美的,Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能。 
  可以将native方法比作Java程序同C程序的接口,其实现步骤:

       1)在Java中声明native()方法,然后编译; 

       2)用javah产生一个.h文件;
  3)写一个.cpp文件实现native导出方法,其中需要包含第二步产生的.h文件(注意其中又包含了JDK带的jni.h文件);
  4)将第三步的.cpp文件编译成动态链接库文件; 
  5)在Java中用System.loadLibrary()方法加载第四步产生的动态链接库文件,这个native()方法就可以在Java中被访问了。

 

7.   java中访问控制符

通常我们可以显示声明的访问控制符有三个:public, private 和 protected。另一种情况是:在成员变量或者方法声明前面不加任何的访问控制符。通过这种方式声明的成员具有缺省访问控制(default access)属性。具有缺省访问属性的类成员的可访问性被限制在包(package)内。 

然后,关于四种访问控制属性的对比,可以直接引用 SO 上的一张非常清晰的对比图表:

Java代码   收藏代码
  1. Modifier    | Class | Package | Subclass | World  
  2. ————————————+———————+—————————+——————————+———————  
  3. public      |  ✔    |    ✔    |    ✔     |   ✔  
  4. ————————————+———————+—————————+——————————+———————  
  5. protected   |  ✔    |    ✔    |    ✔     |   ✘  
  6. ————————————+———————+—————————+——————————+———————  
  7. no modifier |  ✔    |    ✔    |    ✘     |   ✘  
  8. ————————————+———————+—————————+——————————+———————  
  9. private     |  ✔    |    ✘    |    ✘     |   ✘  

 

这张图表可以这样解读(以 protected 为例):

proctected 访问控制符所修饰的类成员在声明该成员的类、类所在的包中的所有其他类以及该类的所有子类中是可见的,而对除此之外的其他类是不可见的。

 

需要注意的一点是,缺省访问控制的类成员只是包内可见,如果其子类也同一个包内,那么也是子类可见的。但是,由于对包外声明的子类是不可见的,所以有上图标中的第4行第4列的✘

 

另外,值得领会的另一个问题是:在实际编程中应该如何选择使用哪一种访问控制符?总的来说,访问控制符设计的初衷是针对 OO 中的封装性 - 应该尽量将信息隐藏。类成员的访问权限放的越开,日后对于该类成员的任何改变就越要谨慎,因为这个类成员可能被很多人使用。如何选择,应该充分考虑类成员的最终用途。

一个值得注意的Java和C++不同之处,同一个Package中,一个class的protected成员函数,可以被同一个package中的其他类访问到。C++中,一个类的protected成员函数只能被自己和自己的子类访问到,其他类是访问不到的。


参考资源:

[1]. Java中PreparedStatement和Statement的用法区别

[2]. java中 == 与 equal 的区别

[3].详解Java中super的几种用法并与this的区别

[4].java的system.arraycopy()方法

[5].牛客网

[6].Java 类成员的访问控制符

你可能感兴趣的:(编程语言基础)