1、.java源文件:
一个以”.java“为后缀的源文件:只能有一个与文件名相同的类,可以包含其他类。
2、类方法:
类方法:类中用static修饰的方法(非static为实例方法) | 在类方法中调用本类的类方法时,可以直接调用。 |
---|---|
在类方法中不能有this关键字,直接调用类方法即可。 | 类方法中可以通过创建实例对象调用类的实例方法。 |
3、super和this关键字
在子类构造器中使用super()显示调用父类的构造方法,super()必须写在子类构造方法的第一行,否则编译不通过;
this:
属性:this属性表示找到本类的属性,如果本类没有找到则继续查找父类;
方法:this方法表示找到本类的方法,如果本类没有找到则继续查找父类;
构造:必须放在构造方法的首行,不能与super关键字同时出现;
特殊:表示当前对象;
super:
属性:super属性直接在子类之中查找父类中的指定属性,不再查找子类本身属性;
方法:super方法直接在子类之中查找父类中的指定方法,不再查找子类本身方法;
构造:必须放在构造方法首行,不能与this关键字同时出现。
super和this关键字 |
---|
1)调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。 2)super从子类中调用父类的构造方法,this()在同一类内调用其它方法。 3)super()和this()均需放在构造方法内第一行。 4)尽管可以用this调用一个构造器,但却不能调用两个。 5)this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。 6)this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。 7)从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。 |
4、抽象类
1、抽象类不能被实例化,实例化的工作应该交由它的子类来完成,它只需要有一个引用即可。
2、抽象方法必须由子类来进行重写。
3、只要包含一个抽象方法的类,该类必须要定义成抽象类,不管是否还包含有其他方法。
4、抽象类中可以包含具体的方法,当然也可以不包含抽象方法。
5、子类中的抽象方法不能与父类的抽象方法同名。
6、abstract不能与final并列修饰同一个类。(abstract需要子类去实现,而final表示不能被继承,矛盾。)
7、abstract 不能与private、static、final或native并列修饰同一个方法。
A、final修饰的类为终态类,不能被继承,而抽象类是必须被继承的才有其意义的,因此,final是不能用来修饰抽象类的。
B、 final修饰的方法为终态方法,不能被重写。而继承抽象类,必须重写其方法。
C、抽象方法是仅声明,并不做实现的方法。
5、访问权限:
(1)访问权限修饰词:
1)public(公共的):表明该成员变量或方法对所有类或对象都是可见的,所有类或对象都可以直接访问;
2)protected(受保护的):表明成员变量或方法对该类本身&与它在同一个包中的其它类&在其它包中的该类的子类都可见;
3)default(默认的,不加任何访问修饰符):表明成员变量或方法只有自己&其位于同一个包内的类可见;
4)private(私有的):表明该成员变量或方法是私有的,只有当前类对其具有访问权限。
由大到小:public(接口访问权限)、protected(继承访问权限)、包访问权限(没有使用任何访问权限修饰词)、private(私有无法访问)
protected表示就类用户而言,这是private的,但对于任何继承于此类的导出类或其他任何位于同一个包内的类来说,却是可以访问的。(protected也提供了包内访问权限)
private和protected一般不用来修饰外部类,而public、abstract或final可以用来修饰外部类(如果用private和protected修饰外部类,会使得该类变得访问性受限)。
(2)访问权限注意点:
1、类的访问权限,只能是包访问权限(默认无访问修饰符即可)或者public。若把一个类中的构造器指定为private,则不能访问该类,若要创建该类的对象,则需要再该类的static成员内部创建,如单例模式。
2、如果没能为类访问权限指定一个访问修饰符,默认得到包访问权限,则该类的对象可以由包内任何其他类创建,但是包外不可以。
3、访问权限的控制,也称为具体实现的隐藏。制定规则(如使用访问权限,设定成员所遵守的界限),是防止客户端程序员对类随心所欲而为。
(3)控制对成员的访问权限的两个原因:
· 使用户不要碰触那些不该碰触的部分,对类内部的操作是必要的,不属于客户端程序员所需接口的一部分;
· 让类库设计者可以更改类的内部工作方式,而不会对客户端程序员产生重大影响;访问权限控制可以确保不会有任何客户端程序员依赖于类的底层实现的任何部分。
(4)对某成员的访问权的唯一途径:
· 1.该成员为public;
· 2.通过不加访问权限修饰词并将其他类放置在同一个包内的方式给成员赋予包访问权。
· 3.继承技术,访问protected成员
· 4.提供访问器和变异器(get/set方法),以读取和改变数值。
6、值传递与引用传递
值传递:Java中原始数据类型都是值传递,传递的是值的副本,形参的改变不会影响实际参数的值;
引用传递: 传递的是引用类型数据,包括String,数组,列表,map,类对象等类型,形参与实参指向的是同一内存地址,因此形参改变会影响实参的值。
7、封装:
把数据和方法包装进类中,以及实现的隐藏,共同称作封装。结果是一个同时带有特征和行为的数据类型。
8、组合、继承:
(1)组合:
定义:只需在新的类中产生现有类的对象,由于新的类是由现有类的对象所组成, 称为组合。组合技术知识将对象引用置于新类中即可。
缺点:将一个成员对象置于所要构造的类中(组合),在新类中暴露这个成员对象的所有方法(继承),需要折中(代理),可以选择只提供在成员对象中的方法的某个子集。
特点:
· 1.has-a关系用组合;
· 2.组合技术通常用于想在新类中使用现有类的功能而非它的接口这种情形。在新类中嵌入某个对象,让其实现所需要的功能,但新类的用户看到的只是为新类所定义的接口,而非所嵌入对象的接口。
(2)继承:
定义:按照现有类的类型来创建新类 ,无需改变现有类的形式,采用现有类的形式并在其增加新代码,称为继承。通过关键字extends实现。
特点:
· 1.当创建一个类时,总在继承。(除非明确指明继承类,否则都是隐式第继承根类Object)
· 2.为了继承,一般将所有的数据成员都指定为private,将所有的方法指定为public。
· 3.可以将继承视作是对类的复用;
· 4.is-a关系用继承;
· 5.继承允许对象视为自身的类型或其基类型加以处理;
· 6.如果向上转型,不能调用那些新的方法(如Animal an = new Cat(),an是不能调用Cat中有的而Animal中没有的方法,会返回一条编译时出错消息),所以向上转型会丢失具体的类型信息;
注意:
1.构造方法不能被继承;方法和属性可以被继承;
2.子类的构造方法隐式地调用父类的不带参数的构造方法;
3.当父类没有不带参数的构造方法时,子类需要使用super来显示调用父类的构造方法,super指的是对父类的引用
4.super关键字必须是构造方法中的第一行语句。特例如下
当两个方法形成重写关系时,可在子类方法中通过super.run()形式调用父类的run()方法,其中super.run()不必放在第一行语句,因此此时父类对象已经构造完毕,先调用父类的run()方法还是先调用子类的run()方法是根据程序的逻辑决定的。
总结:
代理使用时,可以拥有更多的控制力,可以选择只提供在成员对象中的方法的某个子集;
组合和继承都允许在新的类中放置子对象,组合是显式地放置,继承是隐式的做;
组合和继承都能从现有类型中生成新类,组合一般是将现有类型作为新类型底层实现的一部分加以复用,而继承复用的是接口。优先使用组合。
9、final关键字
1)使用范围:数据、方法和类
2)final关键字:final可以修饰属性、方法、类。
3)final修饰类:当一个类被final所修饰时,表示该类是一个终态类,即不能被继承。
4)final修饰方法:当一个方法被final所修饰时,表示该方法是一个终态方法,即不能被重写(Override)。
5)final修饰属性:当一个属性被final所修饰时,表示该属性不能被改写。
(1)final数据:
· 1.编译时常量:是使用static和 final修饰的常量,全用大写字母命名,且字与字之间用下划线隔开。(不能因为数据是final的就认为在编译时就知道值,在运行时也可以用某数值来初始化某一常量)
· 2.final修饰基本数据类型和对象引用:对于基本类型,final修饰的数值是恒定不变;而final修饰对象引用,则引用恒定不变(一旦引用被初始化指向一个对象,就不能改为指向另一个对象),但是对象本身的内容可以修改。
· 3.空白final:空白final是指被声明为final但又未给定初值的域,无论什么情况,编译器都保证空白final在使用被初始化。必须在域的定义处或每个构造器中用表达式对final进行赋值。
· 4.final参数:final修饰参数后,在方法体中不允许对参数进行更改,只可以读final参数。主要用于向匿名类传递数据。
(2)final方法:
· 1.使用final修饰方法原因:将方法锁定以及效率问题。将方法锁定:防止任何继承类修改final方法的含义,确保该方法行为保持不变,且不会被覆盖;效率:早期Java实现中同意编译器将针对该方法的所有调用转为内嵌调用。
· 2.类中所有的private方法都隐式地指定为final的。
(3)final类:
· 1.将某个类整体定义为final时,则不继承该类,不能有子类。
10、初始化及类的加载
1.加载的含义:通常,加载发生在创建类的第一个对象时,但访问static域或static方法时,也会发生加载。static的东西只会初始化一次。
2.加载过程:加载一个类的时候,首先去加载父类的静态域,然后再加载自身的静态域,之后去初始化父类的成员变量,后加载父类的构造方法,最后初始化自身的成员变量,后加载自身的构造方法。(先初始化成员变量,后加载构造函数的原因是,构造函数中可能要用到这些成员变量)
父类静态块——子类静态块——父类块——父类构造器——子类块——子类构造器
最终版本:父类静态域——父类静态块——子类静态域——子类静态块——父类成员变量及代码块——父类构造器——子类成员变量及代码块——子类构造器。
3.加载次数:加载的动作只会加载一次,该类的静态域或第一个实体的创建都会引起加载。
4.变量的初始化:变量的初始化总是在当前类构造器主体执行之前进行的,且static的成员比普通的成员变量先初始化。
11、多态
1.多态只发生在普通方法中,对于域和static方法,不发生多态。子类对象转化为父类型引用时,对于任何域的访问都是由编译器解析。静态方法是与类相关联,而不与单个对象相关联;
2.在继承时,若被覆写的方法不是private,则父类调用方法时,会调用子类的方法,常用的多态性就是当父类引用指向子类对象时。
3.多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
4.多态是同一个行为具有多个不同表现形式或形态的能力。
5.多态就是同一个接口,使用不同的实例而执行不同操作,多态性是对象多种表现形式的体现。
12、构造器
1.为什么强制每个导出类部分都必须调用构造器的原因?(基类的构造器总是在导出类的构造过程中被调用)
只有基类的构造器才具有恰当的知识和权限对自己的元素进行初始化,因此必须令所有的构造器都得到调用。导出类只能访问自己的成员,不能访问基类中的成员(通常是private类型)。
2.编写构造器原则:用尽可能的简单的方法使对象进入正常状态;如果可以的话,避免调用其他方法,因为调用这些方法,有可能会导致初始化未进行,调用的是0值,在构造器内唯一能够安全调用的方法是基类中的final方法(调用不能被覆盖的方法)。
13、基本数据类型与包装类
所有的包装类(8个)都位于java.lang包下,分别是Byte,Short,Integer,Long,Float,Double,Character,Boolean
基本数据类型:byte:8位;short:16位;int:32位;long:64位;float:32位;double:64位;char:16位;boolean:8位。
14、==与equals方法的区别:
(1)基本数据类型与引用数据类型
1.基本数据类型的比较:只能用==;
2.引用数据类型的比较:==是比较栈内存中存放的对象在堆内存地址,equals是比较对象的内容是否相同;
(2)特殊:String作为一个对象
例子一:通过构造函数创建对象时。对象不同,内容相同,"=="返回false,equals返回true
String s1 = newString("java"); String s2 = new String("java");
System.out.println(s1==s2); //false System.out.println(s1.equals(s2)); //true
例子二:同一对象,"=="和equals结果相同
String s1 = newString("java"); String s2 = s1; //两个不同的引用变量指向同一个对象
System.out.println(s1==s2); //true System.out.println(s1.equals(s2)); //true
如果值不相同,对象就不相同,所以"=="和equals结果一样
String s1 = "java"; String s2 = "java"; //此时String常量池中有java对象,直接返回引用给s2;
System.out.println(s1==s2); //true
System.out.println(s1.equals(s2)); //true
字面量形式创建对象时:
如果String缓冲池内不存在与其指定值相同的String对象,那么此时虚拟机将为此创建新的String对象,并存放在String缓冲池内。
如果String缓冲池内存在与其指定值相同的String对象,那么此时虚拟机将不为此创建新的String对象,而直接返回已存在的String对象的引用。
(3)String的字面量形式和构造函数创建对象
1)String s = "aaa";采用字面值方式赋值
1.查找StringPool中是否存再“aaa”这个对象,如果不存在,则在StringPool中创建一个“aaa”对象,然后将String Pool中的这个“aaa”对象的地址返回来,赋给引用变量s,这样s会指向String Pool中的这个“aaa”字符串对象;
2.如果存在,则不创建任何对象,直接将String Pool中的这个“aaa”对象地址返回来,赋给s引用。
2)String s = new String("aaa");
1.首先在StringPool中查找有没有"aaa"这个字符串对象,如果有,则不在String Pool中再去创建"aaa"这个对象,直接在堆中创建一个"aaa"字符串对象,然后将堆中的这个"aaa"对象的地址返回来,赋给s引用,导致s指向了堆中创建的这个"aaa"字符串对象;
2.如果没有,则首先在String Pool中创建一个"aaa"对象,然后再去堆中创建一个"aaa"对象,然后将堆中的这个"aaa"对象的地址返回来,赋给s引用,导致s指向了堆中所创建的这个"aaa"对象。
15、Object类的公有方法
clone()(protected的)、toString()、equals(Object obj)、hashCode()、getClass()、finialize()(protected的)、notify()/notifyAll()、wait()/wait(long timeout)、wait(long timeout,intnaos)
16、try catchfinally
· 1.finally里面的代码一定会执行的;
· 2.当try和catch中有return时,先执行return中的运算结果但是先不返回,然后保存下来计算结果,接着执行finally,最后再返回return的值。
· 3.finally中最好不要有return,否则,直接返回,而先前的return中计算后保存的值得不到返回。
17、面向对象的三大基本特征
封装、继承和多态
(1)封装
隐藏一切可以隐藏的消息,只向外界提供最简单的编程接口;类就是对数据和方法的封装;方法就是对具体实现细节的封装;
(2)继承
从已有的类继承得到继承信息,创建新类的过程,并无需重新编写与原来的类相同的方法或成员变量情况下就可以对这些功能进行扩展。
(3)多态
允许父类型的引用指向子类型的对象。
实现方式:方法重载(编译器绑定,前绑定)和方法重写(运行期绑定,后绑定)
18、静态类和非静态类
(1)静态类
静态类中的字段与方法都必须是static的,静态类不需要实例化就可以使用;
(2)非静态类
非静态类中可以有static的字段与方法,也可以由非static的字段与方法,访问static的字段与方法不需要实例化,但是访问非static的字段与方法时需要实例化。
19、for和foreach循环效率:
for可以不逐个遍历,如每隔一个遍历;也可以从前向后遍历,从后向前遍历;有条件判断,使用已知次数的循环遍历;
foreach只能逐个遍历;只能从前向后遍历;没有执行条件限制,不能向迭代变量赋值;适合集合的遍历;
如果遍历集合或数组时,如果需要访问集合或数组的下标,则最好使用旧式的方式来实现循环或遍历,而不要使用增强的for循环,因为它丢失了下标信息。
20、JNIjava native interface
设计作用:主要实现和其他语言的通信,c和c++。标准的Java类库中可能不支持程序所需的特性,或已经有了一个用其他语言编写的库或程序,但是现在希望用到Java程序中,则需要使用JNI。
使用场景:JDBC实现连接数据库,Thread.sleep()方法。
21、pach和classpath的区别
path是windows的环境属性,用于指定可执行命令的路径;classpath是指在Java程序执行的时候,用于指定类的加载路径。
22、final、finally、finalize的区别
final是Java的一个关键字,用于定义不能被继承的类,不能被覆写的方法,不能修改的常量。
finally是Java的一个关键字,是异常处理操作的统一出口。
finalize是Object类中所提供的一个方法,用于在对象回收之前进行收尾操作。
final
修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法不可以重写(父子类继承关系),但是可以重载(同一个类中)。
finally
异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。一般异常处理块需要。
finalize
· 方法名,Java技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。
· Java中所有类都从Object类中继承finalize()方法。
· 当垃圾回收器(garbage colector)决定回收某对象时,就会运行该对象的finalize()方法。值得C++程序员注意的是,finalize()方法并不能等同与析构函数。Java中是没有析构函数的。C++的析构函数是在对象消亡时运行的。由于C++没有垃圾回收,对象空间手动回收,所以一旦对象用不到时,程序员就应当把它delete()掉。所以析构函数中经常做一些文件保存之类的收尾工作。但是在Java中很不幸,如果内存总是充足的,那么垃圾回收可能永远不会进行,也就是说filalize()可能永远不被执行,显然指望它做收尾工作是靠不住的。
· 那么finalize()究竟是做什么的呢?它最主要的用途是回收特殊渠道申请的内存。Java程序有垃圾回收器,所以一般情况下内存问题不用程序员操心。但有一种JNI(JavaNative Interface)调用non-Java程序(C或C++),finalize()的工作就是回收这部分的内存。
23、Java实现可移植性的原理
Java程序最终通过字节码文件运行,运行的时候字节码需要JVM支持,但是在不同的操作系统中有不同的JVM,程序不用关心操作系统,只关心JVM,只要JVM不改变,程序可以在操作系统间任意移植。
24、Java的数据类型划分
1)当若干个变量参与运算时,结果类型取决于这些变量中表示范围最大的那个变量类型,如有整型int,有双精度浮点型double,有短整型short,则最后的结果类型为double。
2)取模
数据类型 | 默认值 |
---|---|
基本数据类型 | |
数值型:整型:byte、short、int、long 浮点型:float、double | 0 |
字符型:char | '\u0000' |
布尔型:boolean | false |
引用数据类型 | |
数组、类、接口 | null |
25、&和&&、|和||的区别
· &(普通与)和|(普通或)是指所有条件都需要判断;
· &&称为逻辑与(短路与)是如果前面的条件不满足false,则后面的不再进行判断;||称为逻辑或(短路或)如果前面的条件满足true则后面的不再判断;
· 在开发之中为了性能的提高,不需要所有条件进行判断,所以使用短路与和短路或操作;
· &和|除了用于逻辑运算以外,还进行位运算的操作。
·
26、String对象的两种实例化方式的区别
1.首先String对象的实例化有两种:直接赋值和构造方法完成。
2.直接赋值:在常量池中创建该字符串;
3.构造方法:先判断在字符串常量池中是否包含该字符串,若包含该字符串,则在堆中直接创建这个字符串对象并返回该对象引用;若不包含,则先在堆上创建,然后在字符串常量池中也创建,最后把返回堆上对象引用。
27、throw和throws区别
1.throw是语句抛出一个异常。
语法:throw (异常对象);
throw e;
throws是方法可能抛出异常的声明。(用在声明方法时,表示该方法可能要抛出异常)
语法:[(修饰符)](返回值类型)(方法名)([参数列表])[throws(异常类)]{......}
public void doA(int a) throws Exception1,Exception3{......}
2.throw语句用在方法体内,表示抛出异常,由方法体内的语句处理;throws语句用在方法声明后面,表示再抛出异常,由该方法的调用者来处理。
3.throw是具体向外抛异常的动作,已经发生异常,被捕获到,要抛出该异常,所以它是抛出一个异常实例;throws主要是声明这个方法会抛出这种类型的异常,使它的调用者知道要捕获这个异常,倾向于发生,但不一定发生。
28、枚举(Enums)
1.当使用“enum”定义枚举类型时,实质上是继承java.lang.Enum类型;
2.每个枚举的成员其实就是定义的枚举类型的一个实例,他们都被预设为final,所以无法改变他们,也是static成员,所以可以通过类型名称直接使用它们,且他们是公开的public的。
3.特性:final static public的。
4.在编译时期就确定该枚举类型具有几个实例,分别是什么。在运行期间我们无法再使用该枚举类型创建新的实例,这些实例在编译期间就已经完全确定下来。
29、递归
Recursion,就是方法调用自身,对于递归来说,一定有一个出口,让递归结束,只有这样才能保证不出现死循环。
30、可变参数
1.可变参数本质上就是一个数组,对于某个声明了可变参数的方法来说,既可以传递离散的值,也可以传递数组对象。
2.如果将方法中的参数定义为数组,则只能传递数组对象而不能传递离散的值。
3.可变参数必须要作为方法参数的最后一个参数,即一个方法不可能具有两个或以上的可变参数。
31、静态导入
1.使用静态导入import static时,要一直导入到类中的静态成员变量或静态方法。
如:
import static com.ljy.exercise.Person.age;
import staticcom.ljy.exercise.Person.printlnPersonName;
32、集合的元素
集合中存放的依然是对象的引用,而不是对象本身。
集合无法放置原生数据类型,所以需要使用原生数据类型的包装类将其转换为真正的类型。
33、一个类不能既是final的,又是abstract的
因为abstract的主要目的是定义一种约束:让子类去实现这种约定,而final表示该类不能被继承,这样abstract希望该类可以被继承与之矛盾。
34、静态方法
1.static修饰方法,可以通过类名.静态方法名的方式访问,静态方法只能继承,不能重写(Override)。
2.不能在静态方法中使用this关键字;
3.静态的只能访问静态的(因为静态的代码块在构造方法之前就已经开始初始化,而此时非静态的还未开始初始化,如果静态能访问非静态的就会出现发生错误),非静态的可以访问一切。
35、局部变量和成员变量
局部变量使用前必须声明并赋初值;成员变量使用前必须要声明,但可以不赋初值。
36、引用类型
reference type,引用类型用在对象上,一个对象可以被多个引用所指向,但同一时刻,每个引用只能指向唯一的对象,如果一个对象被多个引用所指向,那么无论哪个引用对对象的属性进行修改,都会反映到其他的引用中去。
37、方法和类的定义
(1)类的定义
修饰符 class 类的名字{
//类的内容(包含了属性与方法)
}
(2)方法的定义
修饰符 返回类型 方法名称([参数1,参数2,参数3...]){
//方法体
}
1)方法定义不能嵌套,一个方法中不能定义另一个方法,方法只能定义在类中。
2)形式参数:方法定义时的参数。
3)实际参数:方法调用时所赋予的具体值。
38、break和continue
1)break语句:经常用在循环语句中,用于跳出整个循环,执行循环后面的代码。(如果双重循环,在内循环中使用break,跳出内循环)
2)continue语句:经常用在循环语句中,用于跳出本次循环,开始下一次循环的执行。
3)break与continue可以搭配标签使用。
39、switch语句
40、变量的自增与自减运算
1)关于int b = a++,作用:先将a赋给b,然后再让a自增1。
2)关于int b = ++a,作用:先将a的值自增1,然后再将自增后的a赋给b。
总结:哪个在前,就先做哪一步。
41、Arrays.sort底层实现
基本类型:采用调优的快速排序:当待排序元素小于7个的时候,采用插入排序。
对象类型:采用改进的归并排序;
42、什么是跨平台性?原理是什么?
1)跨平台性:通过Java语言编写的应用程序在不同的系统平台上都可以运行。
2)原理:只要在需要运行Java应用程序的操作系统上,先安装一个Java虚拟机(JVM Java Virtual Machine)即可,由JVM来负责Java程序在该系统中的运行。因为有了JVM,所以同一个Java程序在三个不同的操作系统中都可以执行,这样实现Java程序的跨平台性,也称为Java具有良好的可移植性。
43、JRE与JDK
1)JRE:Java Runtime Environment,Java运行环境,包括JVM和Java程序所需的核心类库等。
2)JDK:Java Development Kit,Java开发工具包,JDK是提供给Java开发人员使用的,其中包含了Java的开发工具(编译工具javac.exe和打包工具jar.exe等),也包括了JRE。所以安装JDK,就不用单独安装JRE。
3)如果是命令行模式:编译器javac进行编译:javac 源文件名.java——编译通过后,对class字节码文件运行:java 类名
4)运行与工作原理
5)path环境变量配置的作用:程序开发过程中,不能将源代码写入JDK的安装目录,因此需要将源程序保存到任意位置的指定目录(英文目录),所以需要使javac指令在任意目录下可以运行。通过配置path环境变量,将javac指令所在目录及JDK安装目录下的bin目录配置到path变量下,即可使javac指令在任意目录下运行。
6)使classpath目录中的.class文件可以在任意目录运行。
7)path和classpath的区别:path环境变量里面记录的是可执行性文件,如.exe文件,对可执行文件先在当前路径去找,如果没找到就去path环境变量中配置的路径去找。而classpath环境变量里记录的是java类的运行文件所在的目录。
44、反射
(1)反射机制
1)定义:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
2)获取Class对象的三种方式
第一种方式:
Person p = new Person();
Class c = p.getClass();
第二种方式:任意类都具备一个class静态属性
Class c2 = Person.class;
第三种方式:将类名作为字符串传递给Class类的静态方法forName
Class c3 =Class.forName("Person");
(2)动态代理
1)在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib
2)Proxy类中的方法创建动态代理类对象
public static Object newProxyInstance(ClassLoaderloader,Class<?>[] interfaces,InvocationHandler h)
最终会调用InvocationHandler的方法
Proxy类中创建动态代理对象的方法的三个参数;
· ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载;
· Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了;
· InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上。
3)InvocationHandler
Object invoke(Object proxy,Method method,Object[] args)
每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke 方法来进行调用。
InvocationHandler接口中invoke方法的三个参数:
· proxy:代表动态代理对象
· method:代表正在执行的方法
· args:代表调用目标方法时传入的实参
4)Proxy.newProxyInstance
创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号。System.out.println(u.getClass().getName());
45、异常
(1)异常介绍
1)编译时异常
除了RuntimeException及其子类,Exception中所有的子类都是,这种异常必须要处理,要不编译通不过
2)运行时异常
RuntimeException及其子类都是,这种异常不用处理,编译会通过,不过这样的程序会有安全隐患,遇到这种异常是需要改代码的
3)严重错误问题
用Error进行描述,这个问题发生后,一般不编写针对代码进行处理,而是要对程序进行修正.通常都是由虚拟机抛出的问题
(2)Throwable中方法
getMessage()
获取异常信息,返回字符串。
toString()
获取异常类名和异常信息,返回字符串。
printStackTrace()
获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
printStackTrace(PrintStream s)
通常用该方法将异常内容保存在日志文件中,以便查阅。
(3)throws和throw的区别
1)throws
· 用在方法声明后面,跟的是异常类名;
· 可以跟多个异常类名,用逗号隔开;
· 表示抛出异常,由该方法的调用者来处理;
· throws表示出现异常的一种可能性,并不一定会发生这些异常。
2)throw
· 用在方法体内,跟的是异常对象名;
· 只能抛出一个异常对象名;
· 表示抛出异常,由方法体内的语句处理;
· throw则是抛出了异常,执行throw则一定抛出了某种异常 。
(4)try和throws区别
如果该功能内部可以将问题处理,用try,如果处理不了,则交由调用者处理,用throws进行抛出异常。
区别:后序程序需要运行,则用try;后序程序不需要继续运行,则用throws;
46、面向对象:
1)思想:是站在现实世界的角度去抽象和解决问题,把数据和行为都看作是对象的一部分,可以让程序员以符合现实世界的思维方式来编写和组织程序。
2)原则:
单一职责:一个类只做它该做的事(高内聚);
开放封闭:对扩展开放,对修改关闭;
里氏替换:任何时候都可用子类型替换父类型;
依赖倒置:面向接口编程(抽象类型可被任何一个子类所替代);
合成聚和复用:优先使用聚合或合成关系复用代码;
接口隔离:一个接口只应描述一种能力,接口应该是高内聚的(小而专一);
迪米特法则:最少知识原则,一个对象应对其他对象尽可能少的了解。
47、数组和容器的区别
1)效率:数组是一种效率最高的存储和随机访问对象引用序列的方式,数组就是一个简单的线性序列,这使得元素访问非常快速,可以通过整型索引值访问元素;
2)大小:数组对象的大小被固定,并且在其生命周期中不可改变;容器如ArrayList可以动态扩容,通过创建一个新实例,然后把旧实例中所有的引用移到新实例中,从而实现更多空间的自动分配;
3)数据类型:数组可以持有基本类型,数组持有某种具体类型,通过编译器检查,防止插入错误类型和抽取不当类型;容器通过泛型,指定并检查它们所持有对象的类型,并且有了自动包装机制,好像是能够持有基本数据类型。
注意:数组的比较是是通过equals()方法,用来比较整个数组,同样,此方法针对所有基类类型与Object都做了重载,数组相等的条件是元素个数必须相等,并且对应位置的元素也相等,这可以通过对每一个元素使用equals()作比较判断。
48、Arrays的方法
java.util类库中的Arrays类,有一套用于数组的static实用方法。有6个基本方法+1个asList()方法。
1)Arrays.asList():接收任意的序列或数组作为其参数,并将其转变为List容器;
2)equals():用于比较两个数组是否相等(deepEquals()用于多维数组);
3)fill():是用同一个数值进行填充数组的各个位置,针对对象而言,就是复制同一个引用进行填充;
4)sort():用于对数组排序;(对于数值排序,小于8的使用插入排序,大于等于8个元素使用快速排序;对于对象排序,使用合并排序);
5)binarySearch():用于在已经排序的数组中查找元素;
6)toString():差生数组的String表示;
7)hashCode():产生数组的散列码;
50、equals()方法的5个条件
1)自反性。对任意x,x.equals(x)一定返回true;
2)对称性。对任意x和y,如果y.equals(x)返回true,则x.equals(y)也返回true;
3)传递性。对任意x、y、z,如果有x.equals(y)返回true,y.equals(z)返回true,则x.equals(z)一定返回true;
4)一致性。对任意x和y,如果对象中用于等价比较的信息没有改变,那么无论调用x.equals(y)多少次,返回的结果应该保持一致,要么一直是true,要么一直是false;
5)对任何不是null的x,x.equals(null)一定返回false。
默认的Object.equals()只是比较对象的地址。
51、public staticvoid main(String[] args)方法的必要性
1)是Java程序的入口方法,JVM在运行程序时,会首先查找main()方法;
2)public是权限修饰符,表明任何类或对象都可以访问这个方法;
3)static表明main()方法是一个静态方法,即方法中的代码是存储在静态存储区的,只要类加载后,就可以使用该方法而不需要通过实例化对象来访问,可以直接通过类名。
4)main()不能用abstract修饰,但可以用final和synchronized修饰,且public与static的顺序可以颠倒。
52、Java程序初始化的顺序
(1)遵循3个原则:
1)静态对象(变量)优先于非静态对象(变量)初始化;
2)父类优先于子类进行初始化;
3)按照成员变量的定义顺序进行初始化,
(2)初始化顺序
父类静态变量、父类静态代码块、子类静态变量、子类静态代码块、父类非静态变量、父类非静态代码块、父类构造函数、子类非静态变量、子类非静态代码块、子类构造函数
53、Java变量类型
(1)变量类型
静态变量、成员变量、局部变量
(2)变量类型的范围
1)静态变量:被static修饰的成员变量称为静态变量,静态变量不依赖于特定的实例,而是被所有实例所共享,只要一个类被加载,JVM就会给类的静态变量分配存储空间,可以通过类名和实例变量名访问静态变量。
2)成员变量:作用范围与类的实例化对象的作用范围相同,当类被实例化时,成员变量就会在内存中分配空间并初始化,直到这个被实例化对象的生命周期结束时,成员变量的声明周期才结束。
3)局部变量:作用域与可见性为它所在的花括号内。
54、ArrayList和LinkedList
1)实现接口:都实现了List接口;
2)底层:ArrayList底层是由数组支持;LinkedList底层是由双向链表实现;
3)内存:ArrayList比LinkedList申请少的内存,因为LinkedList中的每个对象包含数据的同时还包含指向链表中前一个与后一个元素的引用;
4)操作:ArrayList不适合插入或删除,需要移动后面的元素,但适合快速访问;而LinkedList适合插入和删除,因为开销是固定的;
55、快速报错机制
1)出现原因:在迭代遍历某个容器的过程中,另一个进程介入其中,并且插入、删除或修改此容器内的某个对象,则会出现问题:也许迭代过程已经处理过容器中得到该元素了,也许还没处理,也许在调用size()之后容器的尺寸收缩了。
2)快速报错(fail-fast)机制:探查容器上除了你的进程所进行的操作以外的所有变化,一旦发现其他进程修改容器,立即抛出ConcurrentModificationException异常,即不是使用复杂的算法在事后来检查问题。