- Java基本数据类型
-
整数类型:
-
byte :字节型,占1个字节,范围是 - 128到127。用于存储较小的整数,例如在处理文件流或者网络字节流时很有用。
-
short :短整型,占2个字节,范围是 - 32768到32767。在某些特定的内存敏感的场景下可以使用。
-
int :整型,占4个字节,范围是 - 2147483648到2147483647。是最常用的整数类型,用于存储一般的整数数值,如循环计数器、数组下标等。
-
long :长整型,占8个字节,范围是 - 9223372036854775808到9223372036854775807。当需要处理较大的整数时使用,如时间戳等。
-
浮点类型:
-
float :单精度浮点型,占4个字节。它的精度相对较低,但在一些对精度要求不高且需要节省内存的情况下使用,例如简单的图形处理中的坐标等。在Java中,定义 float 类型的变量时,需要在数值后面加上 f 或 F ,如 float f = 3.14f 。
-
double :双精度浮点型,占8个字节。它的精度比 float 高,是Java中默认的浮点类型,用于大多数需要处理小数的情况,如科学计算、金融计算等。
-
字符类型:
-
char :字符型,占2个字节。用于存储单个字符,字符值用单引号括起来,例如 char c = 'A'; 。它可以存储Unicode字符集中的任何字符。
-
布尔类型:
-
boolean :布尔型,占1位(但实际存储可能会占用1个字节)。只有两个值 true 和 false ,用于条件判断和逻辑运算。
- 基本类型和引用类型有什么区别
-
存储方式:
-
基本类型:变量直接存储值。例如, int a = 5; ,变量 a 直接存储整数5这个值。基本类型存储在栈内存中。
-
引用类型:变量存储的是对象的引用(内存地址)。例如, String s = new String("Hello"); ,变量 s 存储的是 String 对象在堆内存中的地址,通过这个地址可以找到真正的对象内容。引用类型的对象本身存储在堆内存中。
-
内存分配:
-
基本类型:在栈中分配内存,其大小是固定的,取决于数据类型。例如 int 类型总是占用4个字节。
-
引用类型:对象在堆内存中分配空间,其大小根据对象的实际内容和结构而定。并且对象的引用(变量)在栈内存中占用一定空间(通常是一个机器字长,如4字节或8字节,取决于操作系统)。
-
赋值操作:
-
基本类型:赋值时是直接复制值。例如, int a = 5; int b = a; ,此时 b 得到了 a 的值5,它们在内存中是独立的两个值。
-
引用类型:赋值时是复制引用(内存地址)。例如, String s1 = new String("Hello"); String s2 = s1; ,此时 s1 和 s2 指向同一个 String 对象,通过任何一个引用修改对象的内容都会影响到另一个引用所指向的对象(对于不可变类如 String ,虽然不能直接修改对象内容,但如果是可变类就会有影响)。
-
比较操作:
-
基本类型:使用 == 比较的是值。例如, int a = 5; int b = 5; , a == b 的结果是 true ,因为它们的值相同。
-
引用类型:使用 == 比较的是引用(内存地址)。例如, String s1 = new String("Hello"); String s2 = new String("Hello"); , s1 == s2 的结果是 false ,因为它们是两个不同的对象,在堆内存中有不同的地址,而 s1.equals(s2) 的结果是 true ,因为 equals 方法在 String 类中被重写来比较字符串的内容。
- 面向对象和面向过程的理解
-
面向过程:
-
编程思想:以过程(函数、方法)为中心,将程序看作是一系列的步骤或操作的组合。强调的是代码的执行流程和顺序,数据通常是分散在各个函数中,通过参数传递来共享。
-
代码结构:程序通常由一个个函数组成,函数之间通过参数传递和返回值来进行交互。例如,在C语言中编写一个计算两个数之和的程序,可能会有一个 add 函数,它接收两个整数参数,然后返回它们的和。
-
优点:流程清晰,对于简单的、线性的问题求解效率高,代码的执行顺序一目了然,易于理解和调试。
-
缺点:对于复杂的系统,代码的可维护性和扩展性较差。当系统规模变大,函数之间的依赖关系会变得复杂,修改一个函数可能会影响到其他很多函数。
-
面向对象:
-
编程思想:以对象为中心,将现实世界中的事物抽象成对象,对象包含数据(属性)和操作(方法)。强调的是对象之间的交互和协作,通过封装、继承和多态等特性来构建复杂的系统。
-
代码结构:程序由类和对象组成。类是对象的模板,定义了对象的属性和方法。例如,在Java中定义一个 Person 类,有 name 和 age 属性,以及 sayHello 方法。可以创建多个 Person 对象,每个对象都有自己的属性值,并且可以调用方法来执行操作。
-
优点:具有良好的封装性,可以隐藏对象内部的细节,提高代码的安全性和可维护性;继承特性可以实现代码的复用,多态可以让代码更加灵活,适应不同的需求。适合开发大型、复杂的软件系统。
-
缺点:对于简单的问题,可能会使代码变得过于复杂。学习成本相对较高,需要理解类、对象、继承、多态等概念。
- 修饰变量的关键字有哪几种
-
访问控制修饰符:
-
public :公共的,被 public 修饰的变量可以在任何类中访问,不受包的限制。
-
private :私有的,被 private 修饰的变量只能在当前类内部访问,外部类无法直接访问。
-
protected :受保护的,被 protected 修饰的变量可以在当前类、同一包中的其他类以及不同包中的子类中访问。
-
(默认,即没有写任何访问控制修饰符):在同一包中的类可以访问,不同包中的类无法访问。
-
其他修饰符:
-
static :静态的,被 static 修饰的变量属于类,而不是属于某个对象。可以通过类名直接访问,所有该类的对象共享这个静态变量。例如, class MyClass{ static int count; } ,可以通过 MyClass.count 来访问这个静态变量。
-
final :最终的,被 final 修饰的变量一旦被赋值,就不能再被修改。如果是基本类型变量,其值不能改变;如果是引用类型变量,其引用不能再指向其他对象,但对象内部的属性可以被修改(如果对象是可变的)。例如, final int a = 5; , a 的值不能再改变。
-
transient :瞬态的,用于修饰变量,主要用于对象序列化。被 transient 修饰的变量在对象序列化时不会被保存,用于标记那些不需要持久化的数据。例如,在一个实现了 Serializable 接口的类中,有一个 transient 修饰的变量,在将对象写入文件或通过网络传输等序列化操作时,这个变量的值不会被保存。
- string和stringBuffer有什么区别
-
可变性:
-
String :是不可变类,一旦创建,其内容不能被改变。例如, String s = "Hello"; s = s + " World"; ,实际上是创建了一个新的 String 对象,原来的 String 对象(内容为 Hello )并没有被修改。这是因为 String 类内部的字符数组是 private final 的,没有提供修改字符数组内容的方法。
-
StringBuffer :是可变类,可以对其内容进行修改。例如, StringBuffer sb = new StringBuffer("Hello"); sb.append(" World"); ,此时 sb 的内容被修改为 Hello World ,没有创建新的对象,而是在原来的对象基础上进行了修改。
-
线程安全性:
-
String :因为是不可变的,所以是线程安全的。多个线程同时访问同一个 String 对象,不会出现数据不一致的问题。
-
StringBuffer :是线程安全的,其内部的方法大多是 synchronized 修饰的,这意味着在多线程环境下可以安全地使用,但是这种线程安全是以一定的性能开销为代价的。
-
性能方面(在字符串拼接操作时):
-
String :在进行频繁的字符串拼接操作时,由于每次拼接都会创建新的对象,会消耗更多的内存和时间。例如,在一个循环中拼接字符串,会创建大量的中间 String 对象。
-
StringBuffer :在频繁拼接字符串时,因为是在同一个对象上进行操作,性能相对较好。但是由于其线程安全的特性,在单线程环境下, StringBuilder (非线程安全版本的 StringBuffer )性能会更好,因为它没有线程安全相关的开销。