1、八大数据类型(基本类型&包装类型)
基本数据类型 | 字节(bit) | 包装类型 |
---|---|---|
byte | 1 | Byte |
short | 2 | Short |
int | 4 | Integer |
long | 8 | Long |
float | 4 | Float |
double | 8 | Double |
char | 2 | Character |
boolean | / | Boolean |
2、&&和&区别
相同点:
- &和&&都是逻辑运算的与运算结果都一样
不同点:
- &可以用于位运算(在二进制中一假即假[0&1=0,0&0=0,1&1=1]
- &&在逻辑运算是具有短路效果(前面一个是假时不会在去判断后面一个是否为假),&则是全部判断.
3、switch的使用和数据变量的类型
switch("值"){
case 值1:代码块1 break;(当"值"1/2/3...和值匹配成功后不加break,会一直执行后面的代码块,直到遇到break或switch执行完成)
case 值2:代码块2 break;
default:代码块(放在所有case的语句后面,它的结束意味switch整体也结束了,break可以省略) } "值"数据类型:byte,short,int,char,Byte,Short,Integer,Character,String,enum
4、 数组定义
一维数组定义:
- 动态定义
int[] arr=new int[10] int [] arr=new int[10]
int arr[]=new int[10] int []arr=new int[10]
- 静态定义
int[] arr={1,2,3} int[] arr=new int[]{1,2,3}
二维数据定义:
int[][] arr = new int[3][4]; 3行4列 动态声明
int[][] arr = new int[3][]; 3行(可以只声明行不声明列,但是不能只声明列,不声明行)
int[][] arr = {{1,2},{5,6},{3,9}}; 静态声明
变形:int [][]arr = new int[3][4];
int arr[][] = new int[3][4];
int []arr[] = new int[3][4];
6、 Java中的修饰符
修饰符 同一类 同包不同类 不同包字符类 不同包 private √ × × × 默认的 √ √ × × protected √ √ √ × public √ √ √ √
static:可以修饰类、方法、变量
被修饰的方法和变量:可以直接通过类名去访问,变量存储在方法区的静态池中归所有对象共享
final修饰符:可以修饰类、方法、变量
修饰的类不能被继承
修饰的方法不可以被重写
修饰的变量为常量,在初始时需要进行赋值,一旦赋值将不能改变
abstract修饰符:可以修饰类和方法
被修饰的类是抽象类,可以有抽象方法,也可以没有抽象方法
被修饰的方法,是抽象方法,不能有方法体
static四连问:
- 是否可以直接从静态类通过类名去调用非静态方法
不可以,调用非静态方法必须把该方法的对象创建出来
- 是否可以用static去修饰局部变量
不可以,因为被static修饰的变量会放在静态方法池中,共所有对象共享,无法起到局部变量
- 静态内部类和内部类的区别:
内部类可以直接访问外部类的属性,而静态内部类只能通过new 外部类去访问
创建内部类对象必须通过new (new 外部类的对象去调用.内部类名()),而静态内部类可以通过 new 外部类名.静态内部类名();
外部类访问内部类需要创建内部类对象在去调用,而静态内部类直接可以通过类型去访问
- static修饰的类是否可以被重写
重写的作用是为了父类和子类的相同签名的方法,具有不同的行为,从而实现了 多态 。但是静态方法是被类直接调用的,和对象无关,不存在父子类对象之间的相同方法不同行为,所以也没有多态
7、方法重载和重写
重载:
方法重载是容许在一个类中可以定义两个相同的方法,它和修饰符和返回值无关,参数列表必须不相同
不相同:参数列表参数个数相同,数据类型不相同
参数列表参数个数不相同,数据类型相同
重写:
发生在子父类关系中,当子类不满意父类继承过来的方法时对其进行重写
满足前提条件:
- 发生在子父类关系中,允许子类定义一个和父类方法名相同的方法
- 子类方法参数列表必须和父类的方法参数列表保持一致
- 子类的返回值的数据类型要么必须和父类返回值类型相同,要么是父类返回值类型的子类
- 子类的重写的方法修饰符不能比父类的修饰符更加严格(小) private < 默认 < protected < public
- 子类抛出的异常不能比父类的大或是和父类相同
- 父类用final修饰的方法不能被重写只能被继承
8、java中的构造方法(构造器)
1、特征:
- 在构造法创建时会有一个默认的无参构造方法
- 人为定义一个构造方法默认的无惨构造方法会消失
- 构造方法不能被继承,因此不能被重写,但是可以进行重载
- 构造方法可以调用普通方法,普通方法不可以调用构造方法
- 构造方法可以调用其他构造方法,通过this();去调用别的构造方法,必须在构造方法的第一行
- 构造方法中的第一行代码默认为super(),调用父类的无参构造方法
2、为什么需要去调用父类的无参构造方法:
因为在在继承的时候会继承一部分父类的属性,而这些都有默认值,需要调用父类的无参构造方法对这些属性进行初始化操作
3、构造放能不能被重写?
重写的前提条件之一是,发生在子类与父类中,允许在子类定义一个和父类方法相同的方法,而构造方法的方法名和类名相同,当A类被B类去继承之后如果对构造方法去重写,那么就会出现两个构造方法,但是构造方法名是和类名相同的,机会导致出现构造方法名与类名不同,就算出现不同包相同类名之后,对其重写,又怎么能确定子类中有两个一样的构造方法呢,这样机就比较矛盾,因此构造方法不可以被继承,也不能被重写
9、 抽象类和抽象方法
背景:
在继承中,我们知道子类可以继承父类的属性和方法,当所有子类都不满意从父类中继承过来的方法时,子类需要重写该方法
#抽象方法特点:
- 用abstract关键字修饰的方法,static、final关键字不能与其搭配修饰
- 抽象方法没有方法体(也就是没有花括号)
# 抽象类特点:
- 若一个类中有抽象方法,那么这个类一定是抽象方法
- 用abstract关键字去修饰的类,目的就是供子类去实现,static、final关键字不能与其搭配
- 抽象类中可以有构造方法,但是不能被实例化
- 抽象类中可以有抽象方法,也可以没有抽象方法
- 抽象类的作用就是供子类去继承的,从而去实现这个抽象方法,若子类没有实现这个抽象方法,则子类也必须定义为抽象类,让子类的子类去实现
#都不满足父类的方法为什么父类还要存在
- 父类中的抽象方法的存在是为了约定子类必须实现的方法,并且提供一种通用的行为或功能
- 实现多态,可以通过父类去调用子类方法,提高代码的灵活性和可扩展性,从而更好的组织和管理代码
10、接口
接口特征:
- 接口没有构造方法
- 接口中允许存在常量,且是public static final 修饰的常量
- 接口中方法默认是public abstract 修饰的抽象方法
- Java8以后允许有default static修饰的方法体的方法
- 接口可以继承多个其他接口,且同时继承多个接口
- 一个类可以同时实现多个接口
为什么有接口:
因为类是现实存在的进行抽象定义得类,而接口是实现能力的
11、抽象类和接口的区别
- 抽象类只能被一个类继承,接口可以被多个接口继承
- 抽象类中的属性定义没有限制,接口对属性定义必须是public static final修饰的常量
- 抽象类中有构造方法不能被实例化,而接口中没有构造方法
- 抽象方法对于修饰符没有限制(可以有抽象方法,也可以有非抽象方法),接口的方法对于修饰符有要求(抽象方法都是public abstract修饰符修饰的,非抽象方法允许static default修饰符修饰的方法)
- 抽象类用于供子类继承(extends),接口用于供类去实现的(implements)
- 抽象类常用于模仿方法设计模式,接口常用于代理设计模式
12、 final、finally、finalize的区别
final:
final修饰的方法只能被继承不能被重写,final修饰的变量为常量在定义的时候需要给初始值,final修饰的类不能派生出子类,所以不能被继承
finally:
通常放在try…catch…的后面构造总是执行代码块,这就意味着程序无论正常执行还是发生异常,这里的代码只要JVM不关闭都能执行,可以将释放外部资源的代码写在finally块中 finalize:
Object类中定义的方法,这个方法是由垃圾收集器在销毁对象时调用的,通过重写finalize()方法可以整理系统资源或者执行其他清理工作。
13、抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?
答:都不能。抽象方法需要子类重写,而静态的方法是无法被重写的(重写的作用是为了父类和子类的相同签名的方法,具有不同的行为,从而实现了 多态 。但是静态方法是被类直接调用的,和对象无关,不存在父子类对象之间的相同方法不同行为,所以也没有多态。),因此二者是矛盾的。本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。
14、 如何跳出当前多重嵌套循环:
第一种方法:使用标记
public static void main(String[] args) { System.out.println("标记前"); ok: for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { System.out.println("i=" + i + ",j=" + j); if (j == 5) break ok; } } System.out.println("标记后"); }
第二种方法:使用flag进行标记
public static void main(String[] args) { System.out.println("标记前"); boolean flag=true; ok: for (int i = 0; i < 10; i++) { for (int j = 0; j < 10&flag; j++) { System.out.println("i=" + i + ",j=" + j); if (j == 5) flag=false; } } System.out.println("标记后"); }
15、 Java中字符串都有哪些类,都有什么区别
String:
它是不可变的的字符串对象,每次值的改变操作都会创建一个新的对象,然后将新的指针指向新的String对象,线程是(自然)安全的;
StringBuffer、StringBuilder:
可以在原有对象的基础上进行操作,StringBuffer线程是安全的(通过锁进行的),StringBuilder线程是不安全的;
区别:
- string和StringBuffer是线程安全的,StringBuilder是线程不安全的,但是string是不可边的,而StringBuffer、StringBuilder是可变的
为什么string和stringbuffed都是安全的,而string用的比较多:
- 在多线程环境下,string是线程自然安全的,而StringBuffer是通过锁去保证线程安全的,stringbuffed性能会降低。
- 不可变性确保了String对象在多线程环境下的安全性,无需担心并发修改导致的数据不一致问题。
- 缓存友好:Java虚拟机有常量池可以对重复的字符串字面量进行内部共享,节省内存并提高性能。这意味着相同的字符串字面量在内存中只会存在一份拷贝。
- 哈希码计算:不可变性使得String对象的哈希码可以在创建时一次性计算并存储,避免每次使用时重新计算,这对于基于哈希的集合(如HashMap、HashSet)操作非常高效。
- 常见编程任务:在日常编程中,直接操作不可变字符串的需求远多于频繁修改字符串内容的需求。例如,处理配置文件、数据库查询结果或网络请求获取的固定数据,进行简单的字符串拼接、格式化输出等任务,通常使用String就足够高效。
- 现代编译器优化:现代Java编译器(如idea)对String拼接进行了优化,对于简单的连续字符串字面量或变量,编译器会自动合并这些字符串,生成单个String对象,从而减轻了频繁创建String对象的负担。这意味着在一些情况下,即使使用+拼接字符串,实际性能影响也可能较小。