java-基础

1、常用的 java api 包、类、接口

  • 包:java.lang.*
  1. 类:Boolean、Byte、Class、ClassLoader、Double、Float、Integer、Long、String、StringBuilder、Thread等
  2. 接口:Cloneable、Comparable、Runnable等
  • java.util.*
  1. 类:ArrayList、Arrays、Base64、Date、HashMap、HashSet、LinkedHashMap、Optional、Random、Collections等
  2. 接口:Collection、Comparator、Iterator、List、Map、Set等
  • java.io.*
  1. 类:BufferedInputStream、BufferedOutputStream、InputStream、OutputStream等
  2. 接口:Serializable
  • java.text.*
  1. 类:SimpleDateFormat
  • java.time.*
  1. 类:LocalDate、LocalDateTime等
  • java.sql.*
  1. 类:Date、DriverManager、Timestamp等
  2. 接口:Connection、Driver、ResultSet、Statement等
  • java.net.*
  1. 类:InetAddress、Socket、URLDecoder、URLEncoder、

2、string类常用的方法?

    equal、split、getBytes、length、replaceAll、toUpperCase、trim、indexOf等

4、& 和 && 的区别?

  • 都可作为逻辑运算符时,&是不管前面的条件是否正确,后面的都会执行;&&是如果前面的不正确,后面的就不会执行(效率高点)
  • & 还可以作为位运算符

5、jdk1.7和1.8的区别?

相对1.7的增强:

    1)支持整数类型(int、short、long、byte)用二进制表示(以ob开头);

    2)switch语句支持string类型;

    3)try-with-resource语句(保证声明的资源在语句结束后都会被关闭);

    4)Catch多个异常;

    5)数字类型的下划线表示(如1_0_3_0063);

    6)泛型实例的创建可以通过类型推断来简化(new后面的内容<>里面可以省略);

    7)并发工具增强(fork-join框架最大的增强)

1.8的新特性:

    1)接口的默认和静态方法(Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法);

    2)Lambda表达式;

    3)方法与构造函数引用

    4)函数式接口:

    5)Annotation 注解:支持多重注解:

    6)新的日期时间 API(提供了新的java.time包,可以用来替代java.util.Date和java.util.Calendar)

    7)Base64编码(在Java 8中,Base64编码成为了Java类库的标准)

    8)JavaScript引擎Nashorn(Nashorn允许在JVM上开发运行JavaScript应用,允许Java与JavaScript相互调用)

    9)Stream的使用(Stream API是把真正的函数式编程风格引入到Java中。其实简单来说可以把Stream理解为MapReduce)

    10)Optional(Java 8引入Optional类来防止空指针异常,Optional类实际上是个容器:它可以保存类型T的值,或者保存null。使用Optional类我们就不用显式进行空指针检查了。)

    11)扩展注解的支持(Java 8扩展了注解的上下文,几乎可以为任何东西添加注解,包括局部变量、泛型类、父类与接口的实现,连方法的异常也能添加注解。)

    12)并行(parallel)数组(支持对数组进行并行处理,主要是parallelSort()方法,它可以在多核机器上极大提高数组排序的速度)

    13)编译器优化(Java 8将方法的参数名加入了字节码中,这样在运行时通过反射就能获取到参数名,只需要在编译时使用-parameters参数)

7、Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型? 

    1)重写和重载是Java多态性的不同表现。

    2)Override(重写)是父类与子类之间多态性的一种表现,Overload(重载)是一个类中多态性的一种表现。

    3)Override(重写):在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。

    4)Overload(重载):在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型

     5)Overload(重载)的方法是可以改变返回值的类型,即参数不同返回值类型可以不同。

8、error和exception有什么区别? 

  • error 表示系统级的错误和程序不必处理的异常,表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。 
  • exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。

9、给我一个你最常见到的runtime exception?

- ArithmeticException(算术异常)
- ClassCastException (类转换异常)
- IllegalArgumentException (非法参数异常)
- IndexOutOfBoundsException (下标越界异常)
- NullPointerException (空指针异常)
- SecurityException (安全异常)

11、Java 中应该使用什么数据类型来代表价格?

  • 在运算的时候,float类型和double很容易丢失精度,所以一般不用来做计算货币。
  • 使用BigDecimal的坏处是性能比double和float差,在处理庞大,复杂的运算时尤为明显,因根据实际需求决定使用哪种类型。
  • BigDecimal构造方法
  1. 不推荐使用BigDecimal(double val)构造器,因为使用该构造器时有一定的不可预知性,当程序使用new BigDecimal(0.1)创建一个BigDecimal对象时,它的值并不是0.1,实际上是一个近似0.1的数。

  2. 建议优先使用基于String的构造器,使用BigDecimal(String val)构造器时可以预知的,写入new BigDecimal("0.1")将创建一个恰好等于0.1的BigDecimal。

  3. 如果必须使用double浮点数作为BigDecimal构造器的参数时,不要使用double作为参数,而应该通过BigDecimal.valueOf(double value)静态方法来创建对象。

BigDecimal BigDecimal(double d); //不允许使用
BigDecimal BigDecimal(String s); //常用,推荐使用
static BigDecimal valueOf(double d); //常用,推荐使用

12、哪个类包含 clone 方法?是 Cloneable 还是 Object?

  • java.lang.Cloneable 是一个标示性接口,不包含任何方法
  • clone 方法在 object 类中定义, 方法clone进行对象拷贝(是浅拷贝)
  • 且 clone() 方法是一个本地方法,这意味着它是由 c 或 c++ 或 其他本地语言实现的。

 

15、我能在不进行强制转换的情况下将一个 double 值赋值给 long 类型的变量吗?

  • 不行
  • double 类型的范围比 long 类型更广,所以必须要进行强制转换。
  • 但是,向下转换时可以直接将 int 常量字面量赋值给 byte、short、char 等数据类型,而不需要强制转换,只要该常量值不超过该类型的表示范围都能自动转换。

16、3*0.1 == 0.3 将会返回什么?true 还是 false?

  • false,因为有些浮点数不能完全精确的表示出来。
  • 数学运算不推荐使用+、-、*、/ 等运算符,可以使用double或者float,如果要求高精度可以使用BigDecimal类

17、int 和 Integer 哪个会占用更多的内存?

  • Integer 对象会占用更多的内存。
  • Integer 是一个对象,需要存储对象的元数据。但是 int 是一个原始类型的数据,所以占用的空间更少

19、32 位和 64 位的 JVM,int 类型变量的长度是多数?

  • 64位系统和32位有什么区别?
  1. 64bit CPU拥有更大的寻址能力,最大支持到16GB内存,而32bit只支持4G内存
  2. 64位 CPU一次可提取64位数据,比32位提高了一倍,理论上性能会提升1倍。但这是建立在64bit操作系统,64bit软件的基础上的。
  • 32 位和 64 位的 JVM,基本数据类型占用的字节数是一样的
byte 1个字节 8位
short 2个字节 16位
int 4个字节 32位
long 8个字节 64位

boolean 1个字节 8位
char 2个字节 16位
float 4个字节 32位
double 8个字节 64位

20、.JVM 选项 -XX:+UseCompressedOops 有什么作用?为什么要使用?

  • 通过 -XX:+UseCompressedOops 选项,JVM 会使用 32 位的 OOP,而不是 64 位的 OOP。
  • 当你将你的应用从 32 位的 JVM 迁移到 64 位的 JVM 时,由于对象的指针从 32 位增加到了 64 位,因此堆内存会突然增加,差不多要翻倍。这也会对 CPU 缓存(容量比内存小很多)的数据产生不利的影响。因为,迁移到 64 位的 JVM 主要动机在于可以指定最大堆大小,通过压缩 OOP 可以节省一定的内存。

JVM参数学习:

参考:https://blog.csdn.net/lsziri/article/details/81200334

           http://www.otpub.com/home/article/details/id/7613.html

21、32 位 JVM 和 64 位 JVM 的最大堆内存分别是多数?

  •     理论上说上 32 位的 JVM 堆内存可以到达 2^32,即 4GB,但实际上会比这个小很多。不同操作系统之间不同,如 Windows 系统大约 1.5 GB,Solaris 大约 3GB。
  • 64 位 JVM允许指定最大的堆内存,理论上可以达到 2^64,这是一个非常大的数字,实际上你可以指定堆内存大小到 100GB。甚至有的 JVM,如 Azul,堆内存到 1000G 都是可能的。

参考:https://www.cnblogs.com/jcj21/p/5225006.html

22、JRE、JDK、JVM 及 JIT 之间有什么不同?

  •     JRE 代表 Java 运行时(Java run-time),是运行 Java 引用所必须的。
  • JDK 代表 Java 开发工具(Java development kit),是 Java 程序的开发工具,如 Java 编译器,它也包含 JRE。
  • JVM 代表 Java 虚拟机(Java virtual machine),它的责任是运行 Java 应用。
  • JIT 代表即时编译(Just In Time compilation),当代码执行的次数超过一定的阈值时,会将 Java 字节码转换为本地代码,如,主要的热点代码会被准换为本地代码,这样有利大幅度提高 Java 应用的性能。

26、java虚拟机内存管理机制?

       自动内存管理机制:
  一、运行时数据区:
    1、程序计数器:线程私有;占用很小的一块内存区域,当前线程所执行字节码的行号指示器,字节码解释器根据计数器的值来选取下一条需要执行的指令
    2、虚拟机栈:线程私有;描述的是java执行方法的内存模型:每个方法执行的同时都会创建一个栈帧,用于存放局部变量表、操作数栈、动态链接、方法出口等信息
       1)存放局部变量表:存放编译期可知的各种基本数据类型、对象引用类型、方法参数、方法内定义的局部变量;存放局部变量表所需要的内存在编译期完成分配;

       2)操作数栈:后入先出栈,在方法的执行过程中会有各种字节码指令写入和提取内容

       3)动态链接:每个栈帧中都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态链接
      此区域会出现两种异常:1)申请的栈深度大于虚拟机所允许的深度则抛出StackOverflowError异常(线程栈的溢出)
                                                  2)栈扩展时无法申请到足够的空间则抛出OutOfMemoryError异常(内存溢出)
    3、本地方法栈:作用和虚拟机栈类似,只不过本地方法栈为虚拟机调用本地方法时服务,而虚拟机栈为虚拟机调用java方法时服务
    4、java堆:被所有线程共享;虚拟机启动时创建;唯一目的就是存放对象实例及数组;java堆是垃圾收集器管理的主要区域,因为也被成为GC堆;
    5、方法区:被所有线程共享;用于存放已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
       1)运行时常量池:方法区的一部分,class文件中除了有类的版本、字段、方法、接口等信息,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用
  二、直接内存
    1、不是虚拟机运行时数据区的一部分,也不是虚拟机定义的内存区域,但也被经常使用;NIO类中可以使用Native本地函数库直接分配堆外内存

30、java获取类的Class对象的方法?

    1) 利用对象实例调用getClass()方法获取该对象的Class实例;
    2) 使用Class类的静态方法forName("包名+类名"),用类的名字获取一个Class实例
    3) 运用 类名.class 的方式来获取Class实例;


    我们知道java世界是运行在JVM之上的,我们编写的类代码,在经过编译器编译之后,会为每个类生成对应的.class文件,这个就是JVM可以加载执行的字节码。运行时期间,当我们需要实例化任何一个类时,JVM会首先尝试看看在内存中是否有这个类,如果有,那么会直接创建类实例;如果没有,那么就会根据类名去加载这个类,当加载一个类,或者当加载器(class loader)的defineClass()被JVM调用,便会为这个类产生一个Class对象(一个Class类的实例),用来表达这个类,该类的所有实例都共同拥有着这个Class对象,而且是唯一的。

31、怎么获取 Java 程序使用的内存?堆使用的百分比?

  • 可以通过 java.lang.Runtime 类中与内存相关方法来获取剩余的内存,总内存及最大堆内存。通过这些方法你也可以获取到堆使用的百分比及堆内存的剩余空间。
  • Runtime.freeMemory() 方法返回剩余空间的字节数,Runtime.totalMemory() 方法总内存的字节数,Runtime.maxMemory() 返回最大内存的字节数。

32、Java 中的编译期常量是什么?使用它又什么风险?

  • 公共静态不可变(public static final )变量也就是我们所说的编译期常量,这里的 public 可选的。
  • 实际上这些变量在编译时会被替换掉,因为编译器知道这些变量的值,并且知道这些变量在运行时不能改变。
  • 这种方式存在的一个问题是你使用了一个内部的或第三方库中的公有编译时常量,但是这个值后面被其他人改变了,但是你的客户端仍然在使用老的值,甚至你已经部署了一个新的jar。为了避免这种情况,当你在更新依赖 JAR 文件时,确保重新编译你的程序。

33、String 是最基本的数据类型吗?

  • 不是。Java中的基本数据类型只有8个:byte、short、int、long、boolean、char、float、double;
  • 除了基本类型(primitive type)和枚举类型(enumeration type:Enum),剩下的都是引用类型(reference type)

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

  • 不正确。
  • 3.4是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换float f =(float)3.4; 或者写成float f =3.4F;

    单精度浮点数在机内占4个字节,用32位二进制描述。双精度浮点数在机内占8个字节,用64位二进制描述。double 和 float 的区别是double精度高,但double消耗内存是float的两倍,double的运算速度比float慢得多

35、用最有效率的方法计算2乘以8?

  • 2 << 3(左移3位相当于乘以2的3次方,右移3位相当于除以2的3次方)。

36、数组有没有length()方法?String有没有length()方法?

  • 数组没有length()方法,有length 的属性。
  • String 有length()方法。
  • JavaScript中,获得字符串的长度是通过length属性得到的,这一点容易和Java混淆。

37、构造器(constructor)是否可被重写(override)?

  • 构造器是无法被继承的,所以不能重写,但是可以重载。
  • 原因:构造器是生产对象的一个途径,假如可以被继承,那么对象就可以被复制了。子类可以通过继承构造器产生父类对象,这样就会出现子类引用指向父类对象,java是不支持向下转型的,只能向上转型。

38、两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?

  • 不对,如果两个对象x和y满足x.equals(y) == true,它们的哈希码(hash code)应当相同。
  • Java对于eqauls方法和hashCode方法是这样规定的:
  1. 如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;
  2. 如果两个对象的hashCode相同,它们并不一定相同,因为可能存在哈希碰撞。

39、是否可以继承String类?

  • String 类是final类,不可以被继承。

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

  • 都不能。
  • 抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。
  • 本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。
  • synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。

41、如何实现对象克隆?

  • 实现Cloneable接口并重写Object类中的clone()方法;
  • 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆

42、String s = new String("xyz");创建了几个字符串对象?

  • 如果String常量池中已经创建了"xyz",则不会继续创建,此时在堆上只创建一个对象new String("xyz");
  • 如果String常量池中没有创建"xyz",则会创建两个对象:
  1. 一个常量池创建的对象"xyz",
  2. 一个在堆上创建的对象是new String("xyz");

43、一个".java"源文件中是否可以包含多个类(不是内部类)?有什么限制?

  •        可以,但一个源文件中最多只能有一个公开类(public class)而且文件名必须和公开类的类名完全保持一致

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

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

        注意:在finally中改变返回值的做法是不好的,因为如果存在finally代码块,try中的return语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕之后再向调用者返回其值,然后如果在finally中修改了返回值,就会返回修改后的值。

46、Collection和Collections的区别?

  • Collection是一个接口,它是Set、List等容器的父接口;
  • Collections是个一个工具类,提供了一系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、排序、线程安全化等等。

47、阐述JDBC操作数据库的步骤?
 

下面的代码以连接本机的Oracle数据库为例,演示JDBC操作数据库的步骤。
    //加载驱动。
 Class.forName("oracle.jdbc.driver.OracleDriver");
    //创建连接。
    Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger");
    //创建语句。
 PreparedStatement ps = con.prepareStatement("select * from emp where sal between ? and ?");
    ps.setInt(1, 1000);
    ps.setInt(2, 3000);
    //执行语句。
    ResultSet rs = ps.executeQuery();
    //处理结果。
 while(rs.next()) {
        System.out.println(rs.getInt("empno") + " - " + rs.getString("ename"));
    }
    //关闭资源。
  finally {
        if(con != null) {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

提示:关闭外部资源的顺序应该和打开的顺序相反,也就是说先关闭ResultSet、再关闭Statement、在关闭Connection。

48、Statement和PreparedStatement有什么区别?哪个性能更好?
    ①PreparedStatement接口代表预编译的语句,它主要的优势在于可以减少SQL的编译错误并增加SQL的安全性(减少SQL注射攻击的可能性);
    ②PreparedStatement中的SQL语句是可以带参数的,避免了用字符串连接拼接SQL语句的麻烦和不安全;
    ③当批量处理SQL或频繁执行相同的查询时,PreparedStatement有明显的性能上的优势,由于数据库可以将编译优化后的SQL语句缓存起来,下次执行相同结构的语句时就会很快(不用再次编译和生成执行计划)。

49、使用JDBC操作数据库时,如何提升读取数据的性能?如何提升更新数据的性能?

  • 要提升读取数据的性能,可以指定通过结果集(ResultSet)对象的setFetchSize()方法指定每次抓取的记录数(典型的空间换时间策略);
  • 要提升更新数据的性能可以使用PreparedStatement语句构建批处理,将若干SQL语句置于一个批处理中执行。 

50、在进行数据库编程时,连接池有什么作用?

  • 由于创建连接和释放连接都有很大的开销(尤其是数据库服务器不在本地时,每次建立连接都需要进行TCP的三次握手,释放连接需要进行TCP四次握手,造成的开销是不可忽视的),
  • 为了提升系统访问数据库的性能,可以事先创建若干连接置于连接池中,需要时直接从连接池获取,使用结束时归还连接池而不必关闭连接,从而避免频繁创建和释放连接所造成的开销,这是典型的用空间换取时间的策略(浪费了空间存储连接,但节省了创建和释放连接的时间)。

    池化技术在Java开发中是很常见的,在使用线程时创建线程池的道理与此相同。基于Java的开源数据库连接池主要有:C3P0、Proxool、DBCP、BoneCP、Druid等。

51、事务的ACID是指什么? 
    - 原子性(Atomic):事务中各项操作,要么全做要么全不做,任何一项操作的失败都会导致整个事务的失败; 
    - 一致性(Consistent):事务结束后系统状态是一致的; 
    - 隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态; 
    - 持久性(Durable):事务完成后所做的改动都会被持久化,即使发生灾难性的失败。通过日志和同步备份可以在故障发生后重建数据。
    补充:关于事务,首先需要知道的是,只有存在并发数据访问时才需要事务。当多个事务访问同一数据时,可能会存在5类问题,包括3类数据读取问题(脏读、不可重复读和幻读)和2类数据更新问题(第1类丢失更新和第2类丢失更新)。

52、JDBC中如何进行事务处理?
        Connection提供了事务处理的方法,通过调用setAutoCommit(false)可以设置手动提交事务;
当事务完成后用commit()显式提交事务;
如果在事务处理过程中发生异常则通过rollback()进行事务回滚。
除此之外,从JDBC 3.0中还引入了Savepoint(保存点)的概念,允许通过代码设置保存点并让事务回滚到指定的保存点。

53、JDBC能否处理Blob和Clob?

  • Blob是指二进制大对象(Binary Large Object)
  • Clob是指大字符对象(Character Large Objec),
  • 因此其中Blob是为存储大的二进制数据而设计的,而Clob是为存储大的文本数据而设计的。
  • JDBC的PreparedStatement和ResultSet都提供了相应的方法来支持Blob和Clob操作。 

54、简述正则表达式及其用途。

  • 在编写处理字符串的程序时,经常会有查找符合某些复杂规则的字符串的需要。
  • 正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。

55、获得一个类的类对象有哪些方式?
- 方法1:类型.class,例如:String.class
- 方法2:对象.getClass(),例如:"hello".getClass()
- 方法3:Class.forName(),例如:Class.forName("java.lang.String")

56、如何通过反射创建对象?
- 方法1:通过类对象调用newInstance()方法,例如:String.class.newInstance()
- 方法2:通过类对象的getConstructor()或getDeclaredConstructor()方法获得构造器(Constructor)对象并调用其newInstance()方法创建对象,例如:String.class.getConstructor(String.class).newInstance("Hello");

57、简述一下你了解的设计模式。

参考:https://www.cnblogs.com/malihe/p/6891920.html

           https://blog.csdn.net/u013490585/article/details/61931532

58、java开发中常用的数据结构?

    1).ArrayList: 元素单个,效率高,多用于查询 
    2).Vector: 元素单个,线程安全,多用于查询 
    3).LinkedList:元素单个,多用于插入和删除 
    4).HashMap: 元素成对,元素可为空 
    5).HashTable: 元素成对,线程安全,元素不可为空  

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

  • 是值传递。
  • Java语言的方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用过程中被改变,但对对象引用的改变是不会影响到调用者的。


60、String和StringBuilder、StringBuffer的区别? 

  • String是只读字符串,也就意味着String引用的字符串内容是不能被改变的。
  • StringBuffer/StringBuilder类表示的字符串对象可以直接进行修改。
  • StringBuilder和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方面都没有被synchronized修饰,因此它的效率也比StringBuffer要高。

61、抽象类(abstract class)和接口(interface)有什么异同? 

抽象类和接口都不能够实例化,但可以定义抽象类和接口类型的引用。
一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类。
接口比抽象类更加抽象,因为抽象类中可以定义构造器,可以有抽象方法和具体方法,而接口中不能定义构造器而且其中的方法全部都是抽象方法。抽象类中的成员可以是private、默认、protected、public的,而接口中的成员全都是public的。抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量。
有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法。

62、是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用? 

  • 不可以
  • 静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,在调用静态方法时可能对象并没有被初始化。

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

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

64、阐述final、finally、finalize的区别。 

  • final:修饰符(关键字)有三种用法:如果一个类被声明为final,意味着它不能再派生出新的子类,即不能被继承,因此它和abstract是反义词。将变量声明为final,可以保证它们在使用中不被改变,被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取不可修改。被声明为final的方法也同样只能使用,不能在子类中被重写。 
  • finally:通常放在try…catch…的后面构造总是执行代码块,这就意味着程序无论正常执行还是发生异常,这里的代码只要JVM不关闭都能执行,可以将释放外部资源的代码写在finally块中。 
  • finalize:Object类中定义的方法,Java中允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在销毁对象时调用的,通过重写finalize()方法可以整理系统资源或者执行其他清理工作。

65、给你一组字符串如:ab9fg5dfs2adas7fte 让你编程输出里面的数字:9527

            String str = "ab9fg5dfs2adas7fte";
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < str.length(); i++) {
				char j = str.charAt(i);
				if (Character.isDigit(j)) { //用于检查其参数是否为十进制数字字符。
					sb.append(String.valueOf(j));
				}
			}

66、java类实现序列化有几种实现方式?都是什么?(二种)

  • 实现Serializable接口:一个对象想要被序列化,那么它的类就要实现 此接口,这个对象的所有属性(包括private属性、包括其引用的对象)都可以被序列化和反序列化来保存、传递。

   序列化的时候的一个关键字:transient(临时的)。它声明的变量实行序列化操作的时候不会写入到序列化文件中去。

  • 实现Externalizable接口:他是Serializable接口的子类,有时我们不希望序列化那么多,可以使用这个接口,这个接口的writeExternal()和readExternal()方法可以指定序列化哪些属性;

67、怎样将GB2312编码的字符串转换为指定编码如“ISO-8859-1”编码的字符串?

String s1 = "你好";
String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");

68、如何实现字符串的反转及替换?

方法一:通过StringBuiler的reverse()的方法,最快的方式
	public String reverseStr(String str) {
		StringBuilder sb = new StringBuilder(str);
		return sb.reverse().toString();
	}
 
方法二:逆序遍历法(将字符串转换成字符数组,可对数组进行逆序遍历)
	public String reverseStr(String str){
		char[] c = str.toCharArray();
		StringBuilder sb = new StringBuilder();
		for(int i=c.length-1;i>=0;i--){
			sb.append(c[i]);
		}
		return sb.toString();
	}
 
方法三:递归法
	public String reverse(String str) {
		if(str == null || str.length() <= 1)
			return str;
		return reverse(str.substring(1)) + str.charAt(0);
	}

69、用Java写一个单例类?

//饿汉式单例
public class SingletonClass1 {

    private SingletonClass1() {
    }

    private static final SingletonClass1 singletonClass1 = new SingletonClass1();

    public static SingletonClass1 getInstance(){
        return singletonClass1;
    }
}


//懒汉式单例
public class SingletonClass2 {
    public SingletonClass2() {
    }
    
    private static volatile SingletonClass2 singletonClass2;
    
    public static SingletonClass2 getInstance(){
        if(singletonClass2 == null){
            synchronized (SingletonClass2.class){
                if(singletonClass2 == null){
                    singletonClass2 = new SingletonClass2();
                }
            }
        }
        return singletonClass2;
    }
}

//静态内部类
//静态内部类方式在SingletonClass3 类被装载时并不会立即实例化,
而是在需要实例化时,调用getInstance方法,才会装载Singleton类,从而完成SingletonClass3 的实例化。
类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,
在类进行初始化时,别的线程是无法进入的。
public class SingletonClass3 {
    private SingletonClass3() {
    }

    private static class Singleton{
        private static final SingletonClass3 singletonClass3 = new SingletonClass3();
    }

    public static SingletonClass3 getInstance(){
        return Singleton.singletonClass3;
    }
}
  • 注意:实现一个单例有两点注意事项
  1. 将构造器私有,不允许外界通过构造器创建对象;
  2. 通过公开的静态方法向外界返回类的唯一实例。
  3. 这里有一个问题可以思考:Spring的IoC容器可以为普通的类创建单例,它是怎么做到的呢?(将bean的作用域设置为singleton) 

70、用Java写一个冒泡排序?

    /**
     * 冒泡排序
     */
    private static void bubbleSort(int[] arr) {
        int temp;
        boolean flag;//标志位:循环开始时置为true,如果循环中发生数据交换(有排序行为),则置为false;如果没有发生数据交换,则跳出循环
        for (int i = 0; i < arr.length - 1; i++) {
            flag = true;
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    flag = false;
                }
            }
            if (flag) {//没有发生交换(表示已经是有序的了)则退出循环;
                break;
            }
        }
    }

71、用Java写一个折半查找(二分查找)?

    private static int binarySerach(int[] arr, int key) {
        int left = 0;
        int right = arr.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (arr[mid] == key) {
                return mid;
            } else if (arr[mid] < key) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return -1;
    }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值