Java基础面试题(全网最齐全)

Java基础面试题(全网最齐全)037数组的初始化方式有哪几种声明时动态赋值: int[] a = new int[5] 默认初始化为0,或int[] a = new int[

大家好,欢迎来到IT知识分享网。Java基础面试题(全网最齐全)"

001 Java语言有哪些优缺点

优点:

  • Java为纯面向对象语言
  • 平台无关性
  • java提供了很多内置的类库。
  • 提供了对Web应用开发的支持
  • 具有较好的安全性和健壮性。
  • 去除了C++语言中难以理解、容易混淆的特性

缺点:

  • 解释型语言,运行速度效率极低,不支持底层操作
  • 取消了指针操作,不够C语言那样灵活。


002 Java提供了哪些基本数据类型?

 Java语言一共提供了8种原始的数据类型(byte,short,int,long,float,double,char, boolean)。

数据类型字节长度范围默认值包装类int4($-2^31$ ~ 2^31-1$)0Integershort2[-32768,32767]0Shortlong8($-2^63$ ~ 2^63-1$)0L 或 01Longbyte1[-128, 127]0Bytefloat432位 IEEE754 单精度范围0.0F 或 0.0fFloatdouble864位 IEEE754 双精度范围0.0Doublechar2Unicode [0, 65535]u0000Characterboolean1true 和 false

false

Boolean

1)int长度数据类型:byte (8 bit)、short (16 bit)、int (32 bit)、long (64 bit)。

  2)float长度数据类型:单精度(32 bit float)、双精度(64 bit double)。

  3)boolean类型变量的取值:ture、false。

  4)char数据类型:unicode字符(16 bit)。


003 Java程序初始化的顺序是怎样的

规则:按这三个规则顺序判断(1)静态先于非静态 (2)父类先于子类 (3)变量先于代码块

如:父类静态变量、父类静态代码块、子类静态变量、子类静态代码块、父类非静态变量、父类非静态代码块、父类构造函数、子类非静态变量、子类非静态代码块、子类构造函数


004 一个Java文件中是否可以定义多个类

一个Java文件中可以定义多个类,但是最多只能有一个类被public修饰,并且这个类的类名与文件名必须相同,若这个文件中没有public的类,则文件名随便是一个类的名字即可。


005 什么是构造函数

构造函数是一种特殊的函数,用来在对象实例化时初始化对象的成员变量。在Java语言中,构造函数具有以下特点。

  1. 构造函数必须与类的名字相同,并且不能有返回值(返回值也不能为void)。

  1. 每个类可以有多个构造函数。当开发人员没有提供构造函数时,编译器在把源代码编译成字节码的过程中会提供一个没有参数默认的构造函数,但该构造函数不会执行任何代码。如果开发人员提供了构造函数,那么编译器就不会再创建默认的构造函数了。

  1. 构造函数可以有0个、1个或1个以上的参数。

  1. 构造函数总是伴随着new操作一起调用,且不能由程序的编写者直接调用,必须要由系统调用。构造函数在对象实例化时会被自动调用,且只运行一次;而普通的方法是在程序执行到它时被调用,且可以被该对象调用多次。

  1. 构造函数的主要作用是完成对象的初始化工作。

  1. 构造函数不能被继承,因此,它不能被覆盖,但是构造函数能够被重载,可以使用不同的参数个数或参数类型来定义多个构造函数。

  1. 子类可以通过super关键字来显式地调用父类的构造函数,当父类没有提供无参数的构造函数时,子类的构造函数中必须显式地调用父类的构造函数。如果父类提供了无参数的构造函数,此时子类的构造函数就可以不显式地调用父类的构造函数,在这种情况下编译器会默认调用父类提供的无参数的构造函数。当有父类时,在实例化对象时会先执行父类的构造函数,然后执行子类的构造函数。

  1. 当父类和子类都没有定义构造函数时,编译器会为父类生成一个默认的无参数的构造函数,给子类也生成一个默认的无参数的构造函数。此外,默认构造器的修饰符只跟当前类的修饰符有关(例如,如果一个类被定义为public,那么它的构造函数也是public)。


006 package有什么作用

具体而言,package主要有以下两个作用:

  • 第一,提供多层命名空间,解决命名冲突,通过使用package,使得处于不同package中的类可以存在相同的名字。
  • 第二,对类按功能进行分类,使项目的组织更加清晰。当开发一个有非常多的类的项目时,如果不使用package对类进行分类,而是把所有类都放在一个package下,这样的代码不仅可读性差,而且可维护性也不好,会严重影响开发效率。


007 面向对象有哪些特征

面向对象的主要特征包括抽象、继承、封装和多态。


008 面向对象的开发方式有什么优点

1)较高的开发效率。采用面向对象的开发方式,可以对现实的事物进行抽象,可以把现实的事物直接映射为开发的对象,与人类的思维过程相似,例如可以设计一个Car类来表示现实中的汽车,这种方式非常直观明了,也非常接近人们的正常思维。同时,由于面向对象的开发方式可以通过继承或者组合的方式来实现代码的重用,因此可以大大地提高软件的开发效率。

2)保证软件的鲁棒性。正是由于面向对象的开发方法有很高的重用性,在开发的过程中可以重用已有的而且在相关领域经过长期测试的代码,因此,自然而然地对软件的鲁棒性起到了良好的促进作用。

3)保证软件的高可维护性。由于采用面向对象的开发方式,使得代码的可读性非常好,同时面向对象的设计模式也使得代码结构更加清晰明了。同时针对面向对象的开发方式,已有许多非常成熟的设计模式,这些设计模式可以使程序在面对需求的变更时,只需要修改部分的模块就可以满足需求,因此维护起来非常方便。


009 面向对象与面向过程有什么区别

具体而言,面向对象与面向过程主要有以下几个方面的不同之处。

  1)出发点不同。面向对象方法是用符合常规思维的方式来处理客观世界的问题,强调把问题域的要领直接映射到对象及对象之间的接口上。而面向过程方法强调的则是过程的抽象化与模块化,它是以过程为中心构造或处理客观世界问题的。

  2)层次逻辑关系不同。面向对象方法则是用计算机逻辑来模拟客观世界中的物理存在,以对象的集合类作为处理问题的基本单位,尽可能地使计算机世界向客观世界靠拢,以使问题的处理更清晰直接,面向对象方法是用类的层次结构来体现类之间的继承和发展。而面向过程方法处理问题的基本单位是能清晰准确地表达过程的模块,用模块的层次结构概括模块或模块间的关系与功能,把客观世界的问题抽象成计算机可以处理的过程。

  3)数据处理方式与控制程序方式不同。面向对象方法将数据与对应的代码封装成一个整体,原则上其他对象不能直接修改其数据,即对象的修改只能由自身的成员函数完成,控制程序方式上是通过“事件驱动”来激活和运行程序。而面向过程方法是直接通过程序来处理数据,处理完毕后即可显示处理结果,在控制程序方式上是按照设计调用或返回程序,不能自由导航,各模块之间存在着控制与被控制、调用与被调用的关系。

  4)分析设计与编码转换方式不同。面向对象方法贯穿于软件生命周期的分析、设计及编码中,是一种平滑过程,从分析到设计再到编码是采用一致性的模型表示,即实现的是一种无缝连接。而面向过程方法强调分析、设计及编码之间按规则进行转换,贯穿于软件生命周期的分析、设计及编码中,实现的是一种有缝的连接。


010 重载和覆盖有什么区别

重载(overload)和覆盖(override)是Java多态性的不同表现方式。其中,重载是在一个类中多态性的一种表现,是指在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型。在使用重载时,需要注意以下几点:

  1)重载是通过不同的方法参数来区分的,例如不同的参数个数、不同的参数类型或不同的参数顺序。

  2)不能通过方法的访问权限、返回值类型和抛出的异常类型来进行重载。

  3)对于继承来说,如果基类方法的访问权限为private,那么就不能在派生类对其重载;如果派生类也定义了一个同名的函数,这只是一个新的方法,不会达到重载的效果。

  覆盖是指派生类函数覆盖基类函数。覆盖一个方法并对其重写,以达到不同的作用。在使用覆盖时需要注意以下几点:

  1)派生类中的覆盖方法必须要和基类中被覆盖的方法有相同的函数名和参数。

  2)派生类中的覆盖方法的返回值必须和基类中被覆盖白方法的返回值相同。

  3)派生类中的覆盖方法所抛出的异常必须和基类(或是其子类)中被覆盖的方法所抛出的异常一致。

  4)基类中被覆盖的方法不能为private,否则其子类只是定义了一个方法,并没有对其覆盖。

  重载与覆盖的区别主要有以下几个方面:

  1)覆盖是子类和父类之间的关系,是垂直关系;重载是同一个类中方法之间的关系,是水平关系。

  2)覆盖只能由一个方法或只能由一对方法产生关系;重载是多个方法之间的关系。

  3)覆盖要求参数列表相同;重载要求参数列表不同。

  4)覆盖关系中,调用方法体是根据对象的类型(对象对应存储空间类型)来决定;而重载关系是根据调用时的实参表与形参表来选择方法体的。


011 抽象类(abstract class)与接口(interface)有什么异同

接口与抽象类的相同点如下

  1)都不能被实例化。

  2)接口的实现类或抽象类的子类都只有实现了接口或抽象类中的方法后才能被实例化。

接口与抽象类的不同点如下

  1)接口只有定义,其方法不能在接口中实现,只有实现接口的类才能实现接口中定义的方法,而抽象类可以有定义与实现,即其方法可以在抽象类中被实现。

  2)接口需要实现(用implements),但抽象类只能被继承(用extends)。一个类可以实现多个接口,但一个类只能继承一个抽象类,因此使用接口可以间接地达到多重继承的目的。

  3)接口强调特定功能的实现,其设计理念是”has-a”关系;而抽象类强调所属关系,其设计理念为”is-a”关系。

  4)接口中定义的成员变量默认为public static final,只能够有静态的不能被修改的数据成员,而且,必须给其赋初值,其所有成员方法都是public、abstract的,而且只能被这两个关键字修饰。而抽象类可以有自己的数据成员变量,也可以有非抽象的成员方法,而且,抽象类中的成员变量默认为default (本包可见),当然也可以被定义为private、protected和public,这些成员变量可以在子类中被重新定义,也可以被重新赋值,抽象类中的抽象方法(其前有abstract修饰)不能用private、static、synchronized、native等访问修饰符修饰,同时方法必须以分号结尾,并且不带花括号。所以,当功能需要累积时,用抽象类;不需要累积时,用接口。

  5)接口被运用于实现比较常用的功能,便于日后维护或者添加删除方法;而抽象类更倾向于充当公共类的角色,不适用于日后重新对里面的代码进行修改。


012 内部类有哪些

内部类可以分为很多种,主要有以下4种:静态内部类(static inner class)成员内部类(member inner class)局部内部类(local inner class)匿名内部类(anonymous inner class)

class outerClass{
 static class innerClass{}     //静态内部类
}

class outerClass{
 class innerClass{} //成员内部类(普通内部类)
}

class outerClass{
 public void menberFunction(){
   class innerClass{} //局部内部类
 }
}

public class MyFrame extends Frame{ //外部类
    public MyFrame(){
      addWindowListener(new WindowAdapter(){ //匿名内部类
        public void windowClosing(WindowEvent e){
         dispose();
         System.exit(0);
        }
      });
    }
}

  静态内部类是指被声明为static的内部类,它可以不依赖于外部类实例而被实例化,而通常的内部类需要在外部类实例化后才能实例化。静态内部类不能与外部类有相同的名字,不能访问外部类的普通成员变量,只能访问外部类中的静态成员和静态方法(包括私有类型)。

  一个静态内部类,如果去掉”static”关键字,就成为成员内部类。成员内部类为非静态内部类,它可以自由地引用外部类的属性和方法,无论这些属性和方法是静态的还是非静态的。但是它与一个实例绑定在了一起,不可以定义静态的属性和方法。只有在外部的类被实例化后,这个内部类才能被实例化。需要注意的是,非静态内部类中不能有静态成员。

  局部内部类指的是定义在一个代码块内的类,它的作用范围为其所在的代码块,是内部类中最少使用到的一种类型。局部内部类像局部变量一样,不能被public、protected、private以及static修饰,只能访问方法中定义为final类型的局部变量。对一个静态内部类,去掉其声明中的”static”关键字,将其定义移入其外部类的静态方法或静态初始化代码段中就成为了局部静态内部类。对一个成员类,将其定义移入其外部类的实例方法或实例初始化代码中就成为了局部内部类。局部静态内部类与静态内部类的基本特性相同。局部内部类与内部类的基本特性相同。

  匿名内部类是一种没有类名的内部类,不使用关键字class、extends、implements,没有构造函数,它必须继承(extends)其他类或实现其他接口。匿名内部类的好处是代码更加简洁、紧凑,但带来的问题是易读性下降。它一般应用于GUI (Graphical User Interface,图形用户界面)编程中实现事件处理等。在使用匿名内部类时,需要牢记以下几个原则:

  1)匿名内部类不能有构造函数。

  2)匿名内部类不能定义静态成员、方法和类。

  3)匿名内部类不能是public、protected、private、static。

  4)只能创建匿名内部类的一个实例。

  5)一个匿名内部类一定是在new的后面,这个匿名类必须继承一个父类或实现一个接口。

  6)因为匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。


013 如何获取父类的类名

Java语言提供了获取类名的方法: getClass().getName() ,开发人员可以调用这个方法来获取类名。


014 this与super有什么区别

在Java语言中,this用来指向当前实例对象,它的一个非常重要的作用就是用来区分对象的成员变量与方法的形参(当一个方法的形参与成员变量的名字相同时,就会覆盖成员变量)。

super可以用来访问父类的方法或成员变量。当子类的方法或成员变量与父类有相同名字时也会覆盖父类的方法或成员变量,要想访问父类的方法或成员变量只能通过super关键字来访问。


015 变量命名有哪些规则

 在Java语言中,变量名、函数名、数组名统称为标识符,Java语言规定标识符只能由字母(a~z,A~Z)、数字(0~9)、下画线(_)和$组成,并且标识符的第一个字符必须是字母、下画线或$。此外,标识符也不能包含空白字符(换行符、空格和制表符)。


016 break、continue以及return有什么区别

  1)break用于直接强行跳出当前循环,不再执行剩余代码。当循环中遇到break语句时,忽略循环体中任何其他语句和循环条件测试,程序控制在循环体后面的语句重新开始。所以,当多层循环嵌套,并且break语句出现在嵌套循环中的内层循环时,它将仅仅只是终止了内层循环的执行,而不影响外层循环的执行。

  2)continue用于停止当次循环,回到循环起始处,进入下一次循环操作。continue语句之后的语句将不再执行,用于跳过循环体中的一部分语句,也就是不执行这部分语句,而不是跳出整个循环执行下一条语句,这就是continue与break的主要区别。简单来说,continue只是中断一次循环的执行而已。

  3)return语句是一个跳转语句,用来表示从一个方法返回(返回一个值或其他复杂类型),可以使程序控制返回到调用该方法的地方。当执行main方法时,return语句可以使程序执行返回到Java运行系统。

  break只能跳出当前的循环,那么如何才能跳出多重循环呢?可以在多重循环的外面定义一个标识,然后在循环体里使用带有标识的break语句,这样即可跳出多重循环,示例如下:

public class Break{

 public static void main(String[]args){
 out:
 for(int i=0;i<5;i++){
   for(int j=0;j<5;j++){
     if(j>=2)
       break out;
        System.out.println(j);
     }
   }
   System.out.println("break");
 }
}


017 final、finally和finalize有什么区别

1)final用于声明属性、方法和类,分别表示属性不可变、方法不可覆盖和类不可被继承(不能再派生出新的子类)。

  2)finally作为异常处理的一部分,它只能用在try/catch语句中,并且附带一个语句块,表示这段语句最终一定被执行,经常被用在需要释放资源的情况下。

3)finalize是Object类的一个方法,在垃圾回收器执行时会调用被回收对象的finalize()方法,可以覆盖此方法来实现对其他资源的回收,例如关闭文件等。需要注意的是,一旦垃圾回收器准备好释放对象占用的空间,将首先调用其finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。


018 assert有什么作用

  断言(assert)作为一种软件调试的方法,提供了一种在代码中进行正确性检查的机制,目前很多开发语言都支持这种机制。它的主要作用是对一个boolean表达式进行检查,一个正确运行的程序必须保证这个boolean表达式的值为true,若boolean表达式的值为false,则说明程序已经处于一种不正确的状态下,系统需要提供告警信息并且退出程序。在实际的开发中, assert主要用来保证程序的正确性,通常在程序开发和测试时使用。为了提高程序运行的效率,在软件发布后,assert检查默认是被关闭的。


019 static关键字有哪些作用

static关键字主要有两种作用

  • 第一,为某特定数据类型或对象分配单一的存储空间,而与创建对象的个数无关。
  • 第二,实现某个方法或属性与类而不是对象关联在一起,也就是说,在不创建对象的情况下就可以通过类来直接调用方法或使用类的属性。

具体而言,在Java语言中,static主要有4种使用情况:成员变量、成员方法、代码块和内部类。

(1)static成员变量

(2)static成员方法

(3)static代码块

(4)static内部类


020 使用switch时有哪些注意事项

switch语句用于多分支选择,在使用switch (expr)时,expr只能是一个枚举常量(内部也是由整型或字符类型实现)或一个整数表达式,其中整数表达式可以是基本类型int或其对应的包装类Integer,当然也包括不同的长度整型,例如short。由于byte、short和char类型的值都能够被隐式地转换为int类型,因此这些类型以及它们对应的包装类型都可以作为switch的表达式。

随着Java语言的发展,在Java 7中,switch开始支持String类型了。


021 volatile有什么作用

volatile是一个类型修饰符(type specifier),它是被设计用来修饰被不同线程访问和修改的变量。被volatile类型定义的变量,系统每次用到它时都是直接从对应的内存当中提取,而不会利用缓存。在使用了volatile修饰成员变量后,所有线程在任何时候所看到变量的值都是相同的。

需要注意的是,由于volatile不能保证操作的原子性,因此,一般情况下volatile不能代替sychronized。此外,使用volatile会阻止编译器对代码的优化,因此会降低程序的执行效率。所以,除非迫不得已,否则,能不使用volatile就尽量不要使用volatile。


022 instanceof有什么作用

instanceof是Java语言中的一个二元运算符,它的作用是判断一个引用类型的变量所指向的对象是否是一个类(或接口、抽象类、父类)的实例,即它左边的对象是否是它右边的类的实例该运算符返回boolean类型的数据。

  常见的用法为:result=object instanceof class。如果object是class的一个实例,那么in-stanceof运算符返回true;如果object不是class的一个实例,或者object是null,那么instan-ceof运算符返回false。


023 strictfp有什么作用

关键字strictfp是strict float point的缩写,指的是精确浮点,它用来确保浮点数运算的准确性。JVM在执行浮点数运算时,如果没有指定strictfp关键字,此时计算结果可能会不精确,而且计算结果在不同平台或厂商的虚拟机上会有不同的结果,导致意想不到的错误。而一旦使用了strictfp来声明一个类、接口或者方法,那么在所声明的范围内,Java编译器以及运行环境会完全依照IEEE二进制浮点数算术标准(IEEE 754)来执行,在这个关键字声明的范围内所有浮点数的计算都是精确的。需要注意的是,当一个类被strictfp修饰时,所有方法都会自动被strictfp修饰。因此,strictfp可以保证浮点数运算的精确性,而且在不同的硬件平台上会有一致的运行结果。


024 什么是不可变类

不可变类(immutable class)是指当创建了这个类的实例后,就不允许修改它的值了,也就是说,一个对象一旦被创建出来,在其整个生命周期中,它的成员变量就不能被修改了。它有点类似于常量(const),即只允许别的程序读,不允许别的程序进行修改。

在Java类库中,所有基本类型的包装类都是不可变类,例如Integer、Float等。此外, String也是不可变类。


025 值传递与引用传递有哪些区别

  (1)值传递

  在方法调用中,实参会把它的值传递给形参,形参只是用实参的值初始化一个临时的存储单元,因此形参与实参虽然有着相同的值,但是却有着不同的存储单元,因此对形参的改变不会影响实参的值。

  (2)引用传递

  在方法调用中,传递的是对象(也可以看作是对象的地址),这时形参与实参的对象指向同一块存储单元,因此对形参的修改就会影响实参的值。

Java中处理8种基本的数据类型用的是值传递,其他所有类型都用的是引用传递,由于这8种基本数据类型的包装类型都是不可变量,因此增加了对“按引用传递”的理解难度。


026 不同数据类型的转换有哪些规则

在Java语言中,当参与运算的两个变量的数据类型不同时,就需要进行隐式的数据类型转换,转换的规则为:从低精度向高精度转换,即优先级满足byte<short<char<int<long<float<double,例如,不同数据类型的值在进行运算时,short类型数据能够自动转为int类型,int类型数据能够自动转换为float类型等。反之,则需要通过强制类型转换来实现。


027 强制类型转换的注意事项有哪些

Java语言在涉及byte、short和char类型的运算时,首先会把这些类型的变量值强制转换为int类型,然后对int类型的值进行计算,最后得到的值也是int类型。因此,如果把两个short类型的值相加,最后得到的结果是int类型;如果把两个byte类型的值相加,最后也会得到一个int类型的值。如果需要得到short类型的结果,就必须显式地把运算结果转换为short类型,例如对于语句short s1=1;s1=s1+1,由于在运行时会首先将s1转换成int类型,因此s1+1的结果为int类型,这样编译器会报错,所以,正确的写法应该short s1=1;s1=(short) (s1+1)。

  有一种例外情况。“+=”为Java语言规定的运算法,Java编译器会对其进行特殊处理,因此,语句short s1=1;s1+=1能够编译通过。


028 运算符优先级是什么

Java语言中有很多运算符,由于运算符优先级的问题经常会导致程序出现意想不到的结果,表4-5详细介绍了运算符的优先级。

优先级运算符(从左向右)1. () []2+(正) -(负) ++ — ~ !3* / %4+(正) -(减)5<< >>(无符号右移) >>>(有符号右移)6< <= > >= instanceof7== !=8&9|10^11&&12||13?:14= += -= *= /= %= &= =|= ^= ~= <<= >>= >>>=

在实际使用时,如果不确定运算符的优先级,最好运用括号运算符来控制运算顺序。


029 Math类中round、ceil和floor方法的功能各是什么

round、ceil和floor方法位于Math类中,Math是一个包含了很多数学常量与计算方法的类,位于java.lang包下,能自动导入,而且Math类里边的方法全是静态方法。下面重点介绍这3个方法代表的含义。

1)round方法表示四舍五入。round,意为“环绕”,其实现原理是在原来数字的基础上先增加0.5然后再向下取整,等同于(int)Math.floor(x+0.5f)。它的返回值类型为int型,例如,Math.round(11.5)的结果为12,Math.round(-11.5)的结果为-11。

  2)ceil方法的功能是向上取整。ceil,意为“天花板”,顾名思义是对操作数取顶, Math.ceil(a),就是取大于a的最小的整数值。需要注意的是,它的返回值类型并不是int型,而是double型。若a是正数,则把小数“入”,若a是负数,则把小数“舍”。

  3)floor方法的功能是向下取整。floor,意为“地板”,顾名思义是对操作数取底。Math.floor(a),就是取小于a的最大的整数值。它的返回值类型与ceil方法一样,也是double型。若a是正数,则把小数“舍”;若a是负数,则把小数“入”。


030 ++i与i++有什么区别

在编程时,经常会用到变量的自增或自减操作,尤其在循环中用得最多。以自增为例,有两种自增方式:前置与后置,即++i和i++,它们的不同点在于i++是在程序执行完毕后进行自增,而++i是在程序开始执行前进行自增。


031 如何实现无符号数的右移操作

Java提供了两种右移运算符:“>>”和“>>>”。其中,“>>”被称为有符号右移运算符,“>>>”被称为无符号右移运算符,它们的功能是将参与运算的对象对应的二进制数右移指定的位数。二者的不同点在于“>>”在执行右移操作时,若参与运算的数字为正数,则在高位补0;若为负数,则在高位补1。而“>>>”则不同,无论参与运算的数字为正数或为负数,在执行运算时,都会在高位补0。

  此外,需要特别注意的是,在对char、byte、short等类型的数进行移位操作前,编译器都会自动地将数值转化为int类型,然后才进行移位操作。由于int型变量只占4Byte (32 bit),因此当右移的位数超过32 bit时,移位运算没有任何意义。所以,在Java语言中,为了保证移动位数的有效性,以使右移的位数不超过32 bit,采用了取余的操作,即a>>n等价于a>>(n%32)。


032 char型变量中是否可以存储一个中文汉字

在Java语言中,默认使用的Unicode编码方式,即每个字符占用两个字节,因此可以用来存储中文。虽然String是由char所组成的,但是它采用了一种更加灵活的方式来存储,即英文占用一个字符,中文占用两个字符,采用这种存储方式的一个重要作用就是可以减少所需的存储空间,提高存储效率。


033 字符串创建与存储的机制是什么

在Java语言中,字符串起着非常重要的作用,字符串的声明与初始化主要有如下两种情况:

  1)对于String s1=new String(”abc”)语句与String s2=new String(”abc”)语句,存在两个引用对象s1、s2,两个内容相同的字符串对象”abc”,它们在内存中的地址是不同的。只要用到new总会生成新的对象。

  2)对于String s1=”abc”语句与String s2=”abc”语句,在JVM中存在着一个字符串池,其中保存着很多String对象,并且可以被共享使用,s1、s2引用的是同一个常量池中的对象。由于String的实现采用了Flyweight的设计模式,当创建一个字符串常量时,例如String s=”abc”,会首先在字符串常量池中查找是否已经有相同的字符串被定义,其判断依据是String类equals(Object obj)方法的返回值。若已经定义,则直接获取对其的引用,此时不需要创建新的对象;若没有定义,则首先创建这个对象,然后把它加入到字符串池中,再将它的引用返回。由于String是不可变类,一旦创建好了就不能被修改,因此String对象可以被共享而且不会导致程序的混乱。


034 “==”、equals和hashCode有什么区别

1)“==”运算符用来比较两个变量的值是否相等。也就是说,该运算符用于比较变量对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能使用“==”运算符。

2)equals是Object类提供的方法之一。每一个Java类都继承自Object类,所以每一个对象都具有equals这个方法。Object类中定义的equals(Object)方法是直接使用“==”运算符比较的两个对象,所以在没有覆盖equals(Object)方法的情况下,equals(Object)与“==”运算符一样,比较的是引用。

3)hashCode()方法是从Object类中继承过来的,它也用来鉴定两个对象是否相等。Object类中的hashCode()方法返回对象在内存中地址转换成的一个int值,所以如果没有重写hash-Code()方法,任何对象的hashCode()方法都是不相等的。


035 String、StringBuffer、StringBuilder和StringTokenizer有什么区别

  • String与StringBuffer的区别

String是不可变类,也就是说,String对象一旦被创建,其值将不能被改变,而StringBuffer是可变类,当对象被创建后仍然可以对其值进行修改。

String与StringBuffer的另外一个区别在于当实例化String时,可以利用构造函数(String s1=new String(”world”))的方式来对其进行初始化,也可以用赋值(String s=”Hello”)的方式来初始化,而StringBuffer只能使用构造函数(StringBuffer s=new StringBuffer(”Hello”))的方式来初始化。

  • StringBuffer与StringBuilder的区别

StringBuilder也是可以被修改的字符串,它与StringBuffer类似,都是字符串缓冲区,但StringBuilder不是线程安全的,如果只是在单线程中使用字符串缓冲区,那么StringBuilder的效率会更高些。

  • StringTokenizer是分割字符串的工具类

总结:在执行效率方面,StringBuilder最高,StringBuffer次之,String最低,鉴于这一情况,一般而言,如果要操作的数据量比较小,应优先使用String类;如果是在单线程下操作大量数据,应优先使用StringBuilder类;如果是在多线程下操作大量数据,应优先考虑StringBuffer类。


036 Java中数组是不是对象

数组是指具有相同类型的数据的集合,它们一般具有固定的长度,并且在内存中占据连续的空间。在C/C++语言中,数组名只是一个指针,这个指针指向了数组的首元素,既没有属性也没有方法可以调用,而在Java语言中,数组不仅有其自己的属性(例如length属性),也有一些方法可以被调用(例如clone方法)。由于对象的特点是封装了一些数据,同时提供了一些属性和方法,从这个角度来讲,数组是对象。每个数组类型都有其对应的类型,可以通过instanceof来判断数据的类型。


037 数组的初始化方式有哪几种

  • 声明时动态赋值: int[] a = new int[5] 默认初始化为0,或int[] a = new int[5]{1,2,3,4,0}
  • 声明时直接静态赋值:nt[] a = {1,2,3,4,5}


038 length属性与length()方法有什么区别

  • length 是数组的属性
  • length() 是字符串的方法,用来计算字符串长度

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/59567.html

(0)
上一篇 2024-05-09 11:26
下一篇 2024-05-10 08:33

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信