Java篇
1、java中字符串拼接 String 和 StringBuilder(StringBuffer)的使用。
字符串拼接是个常用的功能,经常性使用String做字符串拼接,当拼接次数多的时候,使用String方法会消耗大量的性能和时间,因为每次String拼接时都会建立一个新的对象,随着拼接次数的增多,性能消耗、时间消耗会大量增加,这个时候应该使用StringBuilder方法。
2、Java中普通代码块、构造代码块、静态代码块的区别:
执行顺序:静态代码块>main函数>构造代码块>构造函数。
其中静态代码块只执行一次。构造代码块在每次创建对象时都会执行。
普通代码块:在方法或语句中出现的{}就称为普通代码块。普通代码块和一般的语句执行顺序由他们在代码中出现的次序决定--“先出现先执行”
构造块:直接在类中定义且没有加static关键字的代码块称为{}构造代码块。构造代码块在创建对象时被调用,每次创建对象都会被调用,并且构造代码块的执行次序优先于类构造函数。
静态代码块:在java中使用static关键字声明的代码块。静态块用于初始化类,为类的属性初始化。每个静态代码块只会执行一次。由于JVM在加载类时会执行静态代码块,所以静态代码块先于主方法执行。
如果类中包含多个静态代码块,那么将按照"先定义的代码先执行,后定义的代码后执行"。
注意:1 静态代码块不能存在于任何方法体内。2 静态代码块不能直接访问实例变量和实例方法,需要通过类的实例对象来访问。
3、循环结构中break、continue、return和exit的区别
1. break
break语句的使用场合主要是switch语句和循环结构。在循环结构中使用break语句,如果执行了break语句,那么就退出循环,接着执行循环结构下面的第一条语句。如果在多重嵌套循环中使用break语句,当执行break语句的时候,退出的是它所在的循环结构,对外层循环没有任何影响。如果循环结构里有switch语句,并且在switch语句中使用了break语句,当执行switch语句中的break语句时,仅退出switch语句,不会退出外面的循环结构。
2. continue
continue语句是这5种结束循环的方式中最特殊的,因为它并没有真的退出循环,而是只结束本次循环体的执行,所以在使用continue的时候要注意这一点。
在for循环中,首先执行表达式1(注意表达式1在整个循环中仅执行一次),接着执行表达式2,如果满足条件,那么执行循环体,如果在循环体中执行了continue语句,那么就跳转到表达式3处执行,接下进行下一次循环,执行表达式2,看是否满足条件;在while循环中,如果执行了continue语句,那么就直接跳转到表达式处,开始下一次的循环判断;在do while循环体中如果执行了continue语句,那么就跳转到表达式处进行下一次的循环判断,这一点前面已经验证过了。
3. return语句
如果在程序中遇到return语句,那么代码就退出该函数的执行,返回到函数的调用处,如果是main()函数,那么结束整个程序的运行。
如果是在自定义的函数中执行,那么执行return之后就返回到函数的调用处继续往下执行。
4. exit()函数
exit()函数与return语句的最大区别在于,调用exit()函数将会结束当前进程,同时删除子进程所占用的内存空间,把返回信息传给父进程。当exit()中的参数为0时,表示正常退出,其他返回值表示非正常退出,执行exit()函数意味着进程结束;而return仅表示调用堆栈的返回,其作用是返回函数值,并且退出当前执行的函数体,返回到函数的调用处,在main()函数中, return n和exit(n)是等价的。
4、成员变量和局部变量的区别:
1)成员变量定义在类中,整个类中都可以访问。
局部变量定义在函数,语句,局部代码块中,只在所属的区域有效。
2)成员变量存在于堆内存的对象中。 局部变量存在于栈内存的方法中。
3)成员变量随着对象的创建而存在,随着对象的消失而消失。
局部变量随着所属区域的执行而存在,随着所属区域的结束而释放。
4)成员变量都有默认初始化值。 局部变量没有默认初始化值。
5、成员变量和静态变量的区别?
1)两个变量的生命周期不同。
成员变量随着对象的创建而存在,随着对象的被回收而释放。
静态变量随着类的加载而存在,随着类的消失而消失。
2)调用方式不同。
成员变量只能被对象调用。
静态变量可以被对象调用,还可以被类名调用。
3)别名不同。
成员变量也称为实例变量。 静态变量称为类变量。
4)数据存储位置不同。
成员变量数据存储在堆内存的对象中,所以也叫对象的特有数据.
静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据.
静态使用的注意事项:静态方法只能访问静态成员。(非静态既可以访问静态,又可以访问非静态)。静态方法中不可以使用this或者super关键字。主函数是静态的。
6、静态什么时候用?
1,静态变量。
当分析对象中所具备的成员变量的值都是相同的。这时这个成员就可以被静态修饰。只要数据在对象中都是不同的,就是对象的特有数据,必须存储在对象中,是非静态的。如果是相同的数据,对象不需要做修改,只需要使用即可,不需要存储在对象中,定义成静态的。
2,静态函数。
函数是否用静态修饰,就参考一点,就是该函数功能是否有访问到对象中的特有数据。简单点说,从源代码看,该功能是否需要访问非静态的成员变量,如果需要,该功能就是非静态的。如果不需要,就可以将该功能定义成静态的。当然,也可以定义成非静态,但是非静态需要被对象调用,而仅创建对象调用非静态的,没有访问特有数据的方法,该对象的创建是没有意义。
7、一个对象实例化过程:
Person p = new Person();
1)JVM会读取指定的路径下的Person.class文件,并加载进内存,并会先加载Person的父类(如果有直接的父类的情况下).
2)在堆内存中的开辟空间,分配地址。
3)并在对象空间中,对对象中的属性进行默认初始化。
4)调用对应的构造函数进行初始化。
5)在构造函数中,第一行会先到调用父类中构造函数进行初始化。 6)父类初始化完毕后,在对子类的属性进行显示初始化。
7)在进行子类构造函数的特定初始化。
8)初始化完毕后,将地址值赋值给引用变量
8、final关键字:
1)final是一个修饰符,可以修饰类,方法,变量。
2)final修饰的类不可以被继承。
3)final修饰的方法不可以被覆盖。
4)final修饰的变量是一个常量,只能赋值一次。
在java中不直接支持多继承,因为会出现调用的不确定性。所以java将多继承机制进行改良,在java中变成了多实现。
9、抽象类和接口的异同点:
相同点:都是不断向上抽取而来的。
不同点:
1)抽象类需要被继承,而且只能单继承。接口需要被实现,而且可以多实现。
2)抽象类中可以定义抽象方法和非抽象方法,子类继承后,可以直接使用非抽象方法。接口中只能定义抽象方法,必须由子类去实现。
3)抽象类的继承,是is a关系,在定义该体系的基本共性内容。接口的实现是 like a 关系,在定义体系额外功能。
多态的好处:提高了代码的扩展性,前期定义的代码可以使用后期的内容。
多态的弊端:前期定义的内容不能使用(调用)后期子类的特有内容。
10、多态时各组成的变化:多态时,成员的特点:
成员变量。
编译时:参考引用型变量所属的类中的是否有调用的成员变量,有,编译通过,没有,编译失败。
运行时:参考引用型变量所属的类中的是否有调用的成员变量,并运行该所属类中的成员变量。
简单说:编译和运行都参考等号的左边。
成员函数(非静态)
编译时:参考引用型变量所属的类中的是否有调用的函数。有,编译通过,没有,编译失败。
运行时:参考的是对象所属的类中是否有调用的函数。
简单说:编译看左边,运行看右边。
因为成员函数存在覆盖特性。
静态函数。
编译时:参考引用型变量所属的类中的是否有调用的静态方法。
运行时:参考引用型变量所属的类中的是否有调用的静态方法。
简单说,编译和运行都看左边。
其实对于静态方法,是不需要对象的。直接用类名调用即可。
11、内部类和匿名内部类
内部类访问特点:
1)内部类可以直接访问外部类中的成员。
2)外部类要访问内部类,必须建立内部类的对象。一般用于类的设计。
分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容。这时就是还有的事物定义成内部类来描述。
内部类能直接访问外部类中成员,是因为内部类持有了外部类的引用,即外部类名.this。
内部类也可以存放在局部位置上,但是内部类在局部位置上只能访问局部中被final修饰的局部变量。
匿名内部类,就是内部类的简写格式。必须有前提:
内部类必须继承或者实现一个外部类或者接口。
匿名内部类:其实就是一个匿名子类对象。格式:new 父类or接口(){子类内容}
12、异常处理的原则:
1)函数内容如果抛出需要检测的异常,那么函数上必须要声明。否则必须在函数内用trycatch捕捉,否则编译失败。
2)如果调用到了声明异常的函数,要么trycatch要么throws,否则编译失败。
3)什么时候catch,什么时候throws 呢?功能内容可以解决,用catch。解决不了,用throws告诉调用者,由调用者解决。
4)一个功能如果抛出了多个异常,那么调用时,必须有对应多个catch进行针对性的处理。内部又几个需要检测的异常,就抛几个异常,抛出几个,就catch几个。
13、异常的注意事项:
1)子类在覆盖父类方法时,父类的方法如果抛出了异常, 那么子类的方法只能抛出父类的异常或者该异常的子类。
2)如果父类抛出多个异常,那么子类只能抛出父类异常的子集。简单说:子类覆盖父类只能抛出父类的异常或者子类或者子集。
注意:如果父类的方法没有抛出异常,那么子类覆盖时绝对不能抛,就只能try。
14、创建线程的第一种方式:继承Thread类。
创建线程的第二种方式:实现Runnable接口。
1)定义类实现Runnable接口。
2)覆盖接口中的run方法,将线程的任务代码封装到run方法中。
3)通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数进行传递。为什么?因为线程的任务都封装在Runnable接口子类对象的run方法中。所以要在线程对象创建时就必须明确要运行的任务。
4)调用线程对象的start方法开启线程。
实现Runnable接口的好处:
1)将线程的任务从线程的子类中分离出来,进行了单独的封装。按照面向对象的思想将任务的封装成对象。
2)避免了java单继承的局限性。
线程安全问题产生的原因:
1)多个线程在操作共享的数据。
2)操作共享数据的线程代码有多条。
当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算。就会导致线程安全问题的产生。
解决思路;
就是将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其他线程时不可以参与运算的。必须要当前线程把这些代码都执行完毕后,其他线程才可以参与运算。在java中,用同步代码块就可以解决这个问题。
同步代码块的格式:
synchronized(对象) { 需要被同步的代码 ; }
同步的好处:解决了线程的安全问题。
同步的弊端:相对降低了效率,因为同步外的线程的都会判断同步锁。 同步的前提:同步中必须有多个线程并使用同一个锁。
15、final,finally,finalize的区别?
final—修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载。
finally—再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。
finalize—方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。
16、异常分类
一般分为Checked异常和Runtime异常,所有RuntimeException类及其子类的实例被称为Runtime异常,不属于该范畴的异常则被称为CheckedException。
①Checked异常
只有java语言提供了Checked异常,Java认为Checked异常都是可以被处理的异常,所以Java程序必须显示处理Checked异常。如果程序没有处理Checked异常,该程序在编译时就会发生错误无法编译。这体现了Java的设计哲学:没有完善错误处理的代码根本没有机会被执行。对Checked异常处理方法有两种
1 当前方法知道如何处理该异常,则用try...catch块来处理该异常。
2 当前方法不知道如何处理,则在定义该方法是声明抛出该异常。
我们比较熟悉的Checked异常有
Java.lang.ClassNotFoundException
Java.lang.NoSuchMetodException
java.io.IOException
②RuntimeException
Runtime如除数是0和数组下标越界等,其产生频繁,处理麻烦,若显示申明或者捕获将会对程序的可读性和运行效率影响很大。所以由系统自动检测并将它们交给缺省的异常处理程序。当然如果你有处理要求也可以显示捕获它们。我们比较熟悉的RumtimeException类的子类有
Java.lang.ArithmeticException
Java.lang.ArrayStoreExcetpion
Java.lang.ClassCastException
Java.lang.IndexOutOfBoundsException
Java.lang.NullPointerException

浙公网安备 33010602011771号