java基础(2)

1、String、StringBuffer、StringBuilder区别

两种类型的字符串:String和StringBuffer/StringBuilder,他们可以存储和操作字符串。
a)String是只读字符串,表示String引用的字符串内容是不能被改变。
b)StringBuffer/StringBuilder类表示的字符串对象可以直接进行修改。
  StringBuilder和StringBuffer的方法完全相同,区别在于他是在单线程环境下使用,效率比较高。

2、抽象类(abstract class)和接口(interface)的异同

相同点:抽象类和接口都不能实例化。
不同点:a、接口比抽象类更加抽象,因为抽象类可以定义构造方法,可以有抽象方法和具体方法,而接     口中不能定义构造器而且其中的方法全部都是抽象方法。
              b、抽象类中的成员可以是private、默认、protectedpublic,而接口中的成员全部都是public

3、Java中会存在内存泄漏吗,请简单描述。

理论上java因为有垃圾回收机制(GC)不会存在内存泄漏问题;然而在实际考法中,可能会存在无用但可达的队形,这些对象不能被Gc回收,因此也会导致内存泄漏的发生。

4、Java中有几种类型的流

字节流:继承InputStream和OutputStream
字符流:继承Reader、Writer。
面试题--编程实现文件拷贝
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public final class MyUtil {

    private MyUtil() {
        throw new AssertionError();
    }

    public static void fileCopy(String source, String target) throws IOException {
        try (InputStream in = new FileInputStream(source)) {
            try (OutputStream out = new FileOutputStream(target)) {
                byte[] buffer = new byte[4096];
                int bytesToRead;
                while((bytesToRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesToRead);
                }
            }
        }
    }

    public static void fileCopyNIO(String source, String target) throws IOException {
        try (FileInputStream in = new FileInputStream(source)) {
            try (FileOutputStream out = new FileOutputStream(target)) {
                FileChannel inChannel = in.getChannel();
                FileChannel outChannel = out.getChannel();
                ByteBuffer buffer = ByteBuffer.allocate(4096);
                while(inChannel.read(buffer) != -1) {
                    buffer.flip();
                    outChannel.write(buffer);
                    buffer.clear();
                }
            }
        }
    }
}

5、用Java写一个单例类

a)饿汉式单例:
public class Singleton {
   private Singleton(){}
   private static Singleton instance = new Singleton();
   public static Singleton getInstance(){
       return instance;
   }
}
b)懒汉式
public class Singleton {
    private static Singleton instance = null;
    private Singleton() {}
    public static synchronized Singleton getInstance(){
        if (instance == null) instance = new Singleton();
        return instance;
    }
}

6、数据库优化

a)使用关联查询(left join on)查询代替子查询
b)开启事物,当数据库执行多条语句出现错误时,事物会回滚,可以维护数据库的完整性
c)使用索引,索引是提高数据库性能的常用方法。
d)使用外键,事物可维护数据的完整性但是它不能保证数据的关联性,使用外键可以保证数据的关联性

7、面向对象的特征有哪些方面?

1)抽象:抽象是将一类对象的共同特征总结出来构造类的过程
2)继承
3)封装:封装就是隐藏一些可以隐藏的东西,只是向外界提供最简单的编程接口
4)多态性

8、内存中的栈,堆,和静态存储区用法
String str=new String(‘hello’)
str放在栈上,new 创建出来的字符串对象放在堆上,而hello是放在静态存储区。
9、switch 是否可以作用在byte上,能否作用在long上,String上

早期:switch可以是byte,short,char,int ,1.5后引入了枚举类型enum,1.7后可以是String,但是long是不可以的

10、构造器可以被重写?

构造器不能被继承,因此不能被重写,但可以被重载

11、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

是值传递;Java只有值传递。

12、重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?

方法的重载和重写都是实现多态的方式。
重载:编译时多态,重载发生在一个类中,同名的方法可以参数类型不同,参数个数不同
重写:运行时多态,重写发生在子类与父类之间,重写要求父类和子类之间的返回值类型是相同的

13、描述一下JVM 加载class文件的原理机制?

JVM中类的装载是由类加载器ClassLoader和他的子类来实现,Java中的类加载器是一个重要的java运行时系统组件,他负责在运行时查找和装入类文件中的类。

14、char 型变量中能不能存贮一个中文汉字?为什么?

可以存储一个中文汉字,因为java使用的编码是Unicode,一个char占两个字节(16bit)所以存储一个中文是没有问题的。

15、抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?

都不能,抽象的方法需要子类重写,但是静态的方法是无法被重写的,因此二者是矛盾的,本地方法是由本地代码实现的方法,也是矛盾的。synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此是互相矛盾的。
15、Anonymous Inner Class(匿名内部类)是否可以继承其它类?是否可以实现接口?

可以继承其他或者实现其他接口

16、内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?

一个内部类对象可以访问创建他的外部类对象成员,包括私有成员。

17、Java 中的final关键字有哪些用法?

1)修饰类:表示该类不能被继承
2)修饰方法:表示方法不能被重写
3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量)

18、创建对象构造器的调用顺序 :

先初始化静态成员,然后调用父类构造器,在初始化非静态成员,最后调用自身构造器

19、try{}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后?

会执行,在方法返回调用者 

20、什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?

1)java虚拟机是一个可以执行java字节码的虚拟机进程,Java源文件被编译成能够被java虚拟机执行的字节码文件。
2)java被设计成允许应用程序可以运行咋任意的平台,

21、JDK和JRE的区别是什么?

java运行环境JRE是将执行java程序的java虚拟机

22、概括的解释下线程的几种可用状态。

线程在执行过程中,可以处于下面几种状态:
 1)就绪:线程准备运行,不一定立马就能开始执行
 2)运行中:进程正在执行线程的代码
 3)等待中:线程处于阻塞的状态,等待外部的处理结束
 4)睡眠中:线程被强制睡眠
 5I/O阻塞:等待I/O操作完成
 6)同步阻塞:等待获取锁
 7)死亡:线程完成执行

23、同步方法和同步代码块的区别是什么?

在java语言中,每个兑现都有一把锁,线程可以使用synchronized关键字来获取对象上的锁。synchronized关键字可应用在方法级别或者代码块级别。

24、在监视器(Monitor)内部,是如何做线程同步的?程序应该做哪种级别的同步?

监视器和锁在java虚拟机中是一块使用的。监视器监视一块同步代码块,确保一次只有一个线程执行同步代码块。每一个监视器和一个对象引用相关联。线程在获取锁之前不允许执行同步代码

25、什么是死锁?

两个进程都在等待对方执行完毕才能继续往下执行的时候,就发生了死锁,结果两个进程都陷入了无限的等待中。

26、如何确保N个线程可以访问N个资源同时又不导致死锁?

使用多线程的时候,一种简单的避免死锁的方式就是:制定获取锁的顺序,并强制线程按照制定的顺序获取锁,因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁。

27、 数组(Array)和列表(ArrayList)有什么区别?什么时候应该使用Array而不是ArrayList?

1Array可以包含基本类型和对象类型,ArrayList只能包含对象类型
2Array大小是固定的,ArrayList的大小是动态变化的。
3)ArrayList提供了更多的方法和特性。addAll(),removeAll(),iterator()等

28、HashSet和TreeSet有什么区别?

HashSet是由一个hash表来实现的,因此,它的元素是无序的。add(),remove(),contains()方法的时间复杂度是O(1)。
TreeSet是由一个树形的结构来实现的,他里面的元素是有序的,因此,add(),remove(),contains()方法的时间复杂度是O(logn)

29、System.gc()和Runtime.gc()会做什么事情?

这两个方法用来提示JVM要进行垃圾回收。但是立即开始还是延迟进行回收取决于JVM。

30、finalize()方法什么时候被调用?

在释放对象占用的内存之前,垃圾收集器会调用对象的finalize()方法,一般建议在该方法中释放对象持有的资源。

31、如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存?

不会,在下一次垃圾回收周期只能怪,这个对象将是可被回收的。

32、Java堆的结构是什么样子的?什么是堆中的永久代(Perm Gen space)?

JVM的堆是运行时数据区,所有类和实例和数组都是在对上分配内存的,他在JVM启动的时候被创建。对象所占的堆内存是由自动内存管理系统也就是垃圾收集器回收。

33、异常处理完成以后,Exception对象会发生什么变化?

Exception对象会在下一个垃圾回收过程中被回收掉。

34、什么是cookie?session和cookie有什么区别?

cookie是web服务器发送给浏览器的一块信息,浏览器会在本地文件中给每一个web服务器存储cookie。以后浏览器在给特定的web服务器发送请求的时候,同时会发送所有为该服务存储的cookie。
1)客户端无法禁session
2)session能够存储任意的java对象,cookie只能存储String类型的对象。

35、有顺序的Map实现类?

TreeMap和LinkedHashMap是有序的。

36、讲讲你理解的nio和bio?

1)BIO:传统的服务器端同步阻塞I/O处理.
{
 ExecutorService executor = Excutors.newFixedThreadPollExecutor(100);//线程池

 ServerSocket serverSocket = new ServerSocket();
 serverSocket.bind(8088);
 while(!Thread.currentThread.isInturrupted()){//主线程死循环等待新连接到来
 Socket socket = serverSocket.accept();
 executor.submit(new ConnectIOnHandler(socket));//为新的连接创建新的线程
}

class ConnectIOnHandler extends Thread{
    private Socket socket;
    public ConnectIOnHandler(Socket socket){
       this.socket = socket;
    }
    public void run(){
      while(!Thread.currentThread.isInturrupted()&&!socket.isClosed()){死循环处理读写事件
          String someThing = socket.read()....//读取数据
          if(someThing!=null){
             ......//处理数据
             socket.write()....//写数据
          }

      }
      }
注:使用多线程,主要原因在于socket.accept()、socket.read()、socket.write()三个主要函数都是同步阻塞的,
2)NIO:是一中同步非阻塞的I/O模型

37、float f=3.4;是否正确?

不正确。3.4是双精度,将双精度型(double)赋值给浮点型(float)属于下转型会造成精度损失,因此需要强制类型转换 float f=(float)3.4;或者写成float f=3.4L;

38、short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?

对于short s1=1;s1=s1+1;由于1int类型,因此s1+1运算结果也是int型,需要轻质转换类型,才能赋值给short。而后者其中有隐含的强制类型转换。

39、int和Integer有什么区别?

int的包装类时Integer,从java5开始引入了总动装箱/拆箱机制。
public static void main(String[] args) {
        Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;

        System.out.println(f1 == f2);//true
        System.out.println(f3 == f4);//false
    }
    装箱的本质是什么呢?
    当我们给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf,简单的说,如果整形字面量的值在-128127之间,那么就不会new心的Integer对象,而是直接引用常量池中的Integer对象

40、堆栈

1)较新的版本java(6)开始,由于JIT编译器的发展和“逃逸分析”技术的逐渐成熟,栈上分配。标量替换等优化技术使得对象一定分配在堆上的这件事情已经变的不那么绝对。
2)java语言并不要求常量一定只有编译期间才能缠身,运行期间也可以将新的常量放入池中,String类的intern()方法就是这样的。

41、什么情况下用+运算符进行字符串连接比调用StringBuffer/StringBuilder对象的append方法连接字符串性能更好?

字符串+号的本质是创建了StringBuilder对象进行append操作,然后将拼接后的StringBuilder对象用toString方法处理成String对象,

42、为什么不能根据返回类型来区分重载?

无法区分调用的是哪个函数

43、Java 中会存在内存泄漏吗,请简单描述

理论上是可以的,但是在实际开发过程中,例如session(一级缓存)中的对象属于持久态,垃圾回收机器是不会回收这些对象的。然而这些对象中可能存在无用的垃圾对象,如果不及时关闭close或清空,一级缓存记可能导致内存泄漏。

44、打印昨天的日期

import java.time.LocalDateTime;

class YesterdayCurrent {

    public static void main(String[] args) {
        LocalDateTime today = LocalDateTime.now();
        LocalDateTime yesterday = today.minusDays(1);

        System.out.println(yesterday);
    }
}

45、java和javaScript的区别

1)java和javaScript最重要的一个是静态语言,一个是动态语言,目前编程语言的发展趋势是函数式语言和动态语言。

46、什么时候用断言(assert)?

断言用于保证程序最基本,关键的正确性,断言检查通常在开发和测试时开启。为了保证程序的执行效率,在软件发布后断言检查通常是关闭的。

47、列出一些你常见的运行时异常?

算数异常
类转换异常
非法参数异常
下标越界异常
空指针异常
安全异常

48、synchronized关键字的用法?

synchronized关键字可以将对象或者方法标记为同步,以实现对对象和方法的互斥访问。

49、Java中如何实现序列化,有什么意义?

实现Serializable接口,序列化就是一种用来处理对象流的机制,所谓的对象流也就是对对象的内容进行流化,可以对流化的对象进行读写操作。

50、编程实现文件拷贝。(这个题目在笔试的时候经常出现,下面的代码给出了两种实现方案)

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public final class MyUtil {

    private MyUtil() {
        throw new AssertionError();
    }

    public static void fileCopy(String source, String target) throws IOException {
        try (InputStream in = new FileInputStream(source)) {
            try (OutputStream out = new FileOutputStream(target)) {
                byte[] buffer = new byte[4096];
                int bytesToRead;
                while((bytesToRead = in.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesToRead);
                }
            }
        }
    }

    public static void fileCopyNIO(String source, String target) throws IOException {
        try (FileInputStream in = new FileInputStream(source)) {
            try (FileOutputStream out = new FileOutputStream(target)) {
                FileChannel inChannel = in.getChannel();
                FileChannel outChannel = out.getChannel();
                ByteBuffer buffer = ByteBuffer.allocate(4096);
                while(inChannel.read(buffer) != -1) {
                    buffer.flip();
                    outChannel.write(buffer);
                    buffer.clear();
                }
            }
        }
    }
}

51、事物的ACID

A:原子性
C:一致性
I:隔离性
D:持久性
脏读:A事物读取B事物尚未提交的数据并在此基础上操作,而B事物执行回滚,那么A数据读取到的数据就是脏数据。
不可重复读:事物A重新读取前面读取过的数据,发现该数据已经被另一个已提交的事物B修改过了。
幻读:事务A重新执行一个查询,返回一系列符合查询条件的行,发现其中插入了被事物b提交的行。

52、JDBC中如何进行事务处理?

Connection提供了事务处理的方法,通过调用setAutoCommit(false)可以设置手动提交事务,当事务完成后用commit()显示提交事务;如果失败则通过rollback()进行事务回滚。

53、获得一个类的类对象有那些方式?

1)String.class:类型.class
2)对象.getClass()
3)Class.forName(),例如:Class.forName("java.lang.String")。

54、用Java写一个冒泡排序。

import java.util.Comparator;

/**
 * 排序器接口(策略模式: 将算法封装到具有共同接口的独立的类中使得它们可以相互替换)
 * @author骆昊
 *
 */
public interface Sorter {

   /**
    * 排序
    * @param list 待排序的数组
    */
   public <T extends Comparable<T>> void sort(T[] list);

   /**
    * 排序
    * @param list 待排序的数组
    * @param comp 比较两个对象的比较器
    */
   public <T> void sort(T[] list, Comparator<T> comp);
}

import java.util.Comparator;

/**
 * 冒泡排序
 * 
 * @author骆昊
 *
 */
public class BubbleSorter implements Sorter {

    @Override
    public <T extends Comparable<T>> void sort(T[] list) {
        boolean swapped = true;
        for (int i = 1, len = list.length; i < len && swapped; ++i) {
            swapped = false;
            for (int j = 0; j < len - i; ++j) {
                if (list[j].compareTo(list[j + 1]) > 0) {
                    T temp = list[j];
                    list[j] = list[j + 1];
                    list[j + 1] = temp;
                    swapped = true;
                }
            }
        }
    }

    @Override
    public <T> void sort(T[] list, Comparator<T> comp) {
        boolean swapped = true;
        for (int i = 1, len = list.length; i < len && swapped; ++i) {
            swapped = false;
            for (int j = 0; j < len - i; ++j) {
                if (comp.compare(list[j], list[j + 1]) > 0) {
                    T temp = list[j];
                    list[j] = list[j + 1];
                    list[j + 1] = temp;
                    swapped = true;
                }
            }
        }
    }
}

55、用Java写一个折半查找

import java.util.Comparator;

public class MyUtil {

   public static <T extends Comparable<T>> int binarySearch(T[] x, T key) {
      return binarySearch(x, 0, x.length- 1, key);
   }

   // 使用循环实现的二分查找
   public static <T> int binarySearch(T[] x, T key, Comparator<T> comp) {
      int low = 0;
      int high = x.length - 1;
      while (low <= high) {
          int mid = (low + high) >>> 1;
          int cmp = comp.compare(x[mid], key);
          if (cmp < 0) {
            low= mid + 1;
          }
          else if (cmp > 0) {
            high= mid - 1;
          }
          else {
            return mid;
          }
      }
      return -1;
   }

   // 使用递归实现的二分查找
   private static<T extends Comparable<T>> int binarySearch(T[] x, int low, int high, T key) {
      if(low <= high) {
        int mid = low + ((high -low) >> 1);
        if(key.compareTo(x[mid])== 0) {
           return mid;
        }
        else if(key.compareTo(x[mid])< 0) {
           return binarySearch(x,low, mid - 1, key);
        }
        else {
           return binarySearch(x,mid + 1, high, key);
        }
      }
      return -1;
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值