一、java语言概述
1、软件分为:系统软件和应用软件;
2、人机交互方式:图形化界面和命令行方式;
3、常用的dos命令:
答:dir:列出当前目录下所有的文件以及文件夹
Md:创建目录
Rd:删除目录
Cd:进入指定目录
Cd..:退回到上一级目录
Cd\:返回到根目录
Del:删除文件
Exit:退出dos系统
详细见:https://www.cnblogs.com/defen/p/5618226.html
4、jre、jdk、jvm的区别?
答:首先是JDK
JDK(Java Development Kit) 是 Java 语言的软件开发工具包(SDK)。在JDK的安装目录下有一个jre目录,里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和 lib合起来就称为jre。
然后我们来看JRE
JRE(Java Runtime Environment,Java运行环境),包含JVM标准实现及Java核心类库。JRE是Java运行环境,并不是一个开发环境,所以没有包含任何开发工具(如编译器和调试器)
最后JVM也一目了然了
JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
由上图一目了然:
JDK是整个Java的核心,包括了Java运行环境JRE、Java工具和Java基础类库。JRE是运行JAVA程序所必须的环境的集合,包含JVM标准实现及Java核心类库。JVM是整个java实现跨平台的最核心的部分,能够运行以Java语言写的程序。
详细见:https://www.cnblogs.com/mambahyw/p/7978832.html
5、Java语言的特点?
答:
1)java是纯面向对象编程的语言;
2)平台无关性 (一次编译,到处运行;Write Once,Run Anywhere);
3)java提供了许多内置的类库,通过这些类库,简化了开发人员的设计工作,同时缩短了项目开发时间;
4)提供了对Web应用开发的支持,例如,Applet,Servlet,和JSP可以用来开发Web应用程序,,Socket,RMI可以用来开发分布式应用程序的类库;
5)去除了c++中难以理解,容易混淆的特性(如c++中的多继承,头文件,指针,结构,单元,运算符重载,虚拟基础类,使得程序更加严谨,整洁;
6)具有较好的安全性和健壮性。java语言经常会被用在网络环境中,为了增强程序的安全性,java语言提供了一个防止恶意代码攻击的安全机制(数组边界检测和Bytecode检测等),
java的强类型机制,垃圾回收器,异常处理,安全检查机制使得java语言编写的程序有更好的健壮性和鲁棒性。
6、配置环境变量?
答:
第一步:要想配置Java的环境变量,就一定要安装JDK【Java(TM)SE development kit】,然后才能开始进行相关的配置。
执行下载好的JDK安装包,为了避免产生不必要的冲突,所以在安装过程中可以保留默认的安装路径,只需要确认是否必要的可选功能都已被勾选,点击“下一步”等待安装完成就好。
第二步:JDK安装完成后,需要对程序进行测试,检测是否正确完成了安装。单击开始菜单,选择“运行...”,在指令框中输入CMD并回车运行。正确安装的情况下此时会弹出一个黑底的会话框(若出现错误需重新安装),在命令提示符中输入“Java—version”并回车,此时在会话框中会显示程序的版本信息等,表明安装成功了。
第三步:现在开始配置环境变量。右键单击我的电脑,依次选择“属性”、“高级系统设置”、“环境变量”。然后在系统变量栏下点击“新建系统变量”,在会话框的变量名中输入“JAVA_HOME”,在变量值中输入JDK的安装路径(即为之前的默认路径),点击确定。
在系统变量选项栏中查找是否有变量“PATH”,若没有则需要新建系统变量,否则的话选择“编辑系统变量”,在弹出的会话框中在“变量值”文本框的起始位置添加“%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;”或者是直接“%JAVA_HOME%\bin;”,单击确定。
再在选项栏中查找是否有变量“CLASSPATH”,同样若没有则需要新建系统变量,否则的话同样选择编辑系统变量,在会话框的“变量值”中输入“.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;”,单击确定。
最后测试环境变量是否配置成功,在黑底会话框中输入“javac”回车运行。如成功则会输出一系列帮助信息。若出现错误没能安装成功,可将之前新建的几个系统变量删除后按照步骤重新创建即可。
到此,若没有出现新的问题则Java的环境变量配置完成。
第四步:编译一个java程序,然后进行编译。
在编译过程中,通常会出现以下几个问题:
1.在输入“javac <文件路径>”后报错显示“<文件名>不是内部或外部命令,也不是可运行的程序或批处理文件”,这是因为安装路径默认是在C盘中,如果需要编译的文件不在C盘中,则需要先行将路径导入到存放该编译文件的盘中,如编译文件存放在E盘中,在“C:\User\Administrator. ....>”后输入“E”:则将路径导入到了E盘中。再输入相应的指令进行编译。
2.在进行了问题1或者未出现1问题的情况下若还是无法进行编译,则可以考虑将编译文件直接放在所在盘的根目录下再进行编译。
3.第一次编译完成后,系统应该在被编译文件的所在目录中生成一个同名的.class文件,此时应该再次编译这个.class文件,输入指令为:“java <文件名>”,即可完成编译。
7、如何在dos命令下编译运行java代码?
答:Javac xx.java ----------->java xx
注:javac编译成字节码
Java命令执行字节码文件(jvm执行)
8、JVM运行时数据区有哪些?
答:
第一块:PC寄存器
PC寄存器是用于存储每个线程下一步将执行的JVM指令,如该方法为native的,则PC寄存器中不存储任何信息。
第二块:JVM栈
JVM栈是线程私有的,每个线程创建的同时都会创建JVM栈,JVM栈中存放的为当前线程中局部基本类型的变量(java中定义的八种基本类型:boolean、char、byte、short、int、long、float、double)、部分的返回结果以及Stack Frame,非基本类型的对象在JVM栈上仅存放一个指向堆上的地址
第三块:堆(Heap)
它是JVM用来存储对象实例以及数组值的区域,可以认为Java中所有通过new创建的对象的内存都在此分配,Heap中的对象的内存需要等待GC进行回收。
第四块:方法区域(Method Area)
(1)在Sun JDK中这块区域对应的为PermanetGeneration,又称为持久代。
(2)方法区域存放了所加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息,当开发人员在程序中通过Class对象中的getName、isInterface等方法来获取信息时,这些数据都来源于方法区域,同时方法区域也是全局共享的,在一定的条件下它也会被GC,当方法区域需要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。
第五块:运行时常量池(Runtime Constant Pool)
存放的为类中的固定的常量信息、方法和Field的引用信息等,其空间从方法区域中分配。
第六块:本地方法堆栈(Native Method Stacks)
JVM采用本地方法堆栈来支持native方法的执行,此区域用于存储每个native方法调用的状态。
二、基本语法
9、八大基本数据类型?
答:
数据类型 | 字节数 | 位数 | 范围 | 备注 |
Byte | 1 | 8 | -128~127 | 用于表示最小数据单位,如文件中数据(整数类型) |
Short | 2 | 16 | -32768~32767 | (整数类型) |
Int | 4 | 32 | -2^31-1~2^31 (21 亿) | 整数字面量默认都为 int 类型(整数类型) |
Long | 8 | 64 | -2^63-1~2^63 | 在定义的 long 型数据后面加 L或 l(整数类型) |
Float | 4 | 32 | 1 位符号位,8 位指数,23 位有效尾数。 | 在定义的 float 型数据后面加F 或 f;double 类型可不写后缀,但在小数计算中一定要写 D 或 X.X float 的精度没有 long 高,有效位数(尾数)短。 float 的范围大于 long 指数可以很大。 浮点数是不精确的,不能对浮点数进行精确比较。(浮点数类型) |
Double | 8 | 64 | 1 位符号位,11 位指数,52 位有效尾 | 浮点数字面量默认都为 double 类型(浮点数类型) |
Char | 2 | 16 |
| 是整数类型,用单引号括起来的 1 个字符(可以是一个中文字符),使用 Unicode 码代表字符,0~2^16-1(65535) 。 注意事项: 不能为 0个字符。 转义字符:\n 换行 \r 回车 \t Tab 字符 \" 双引号 \\ 表示一个\ 两字符 char 中间用“+”连接,内部先把字符转成 int 类型,再进行加法运算,char 本质就是个数!二进制的,显示的时候,经过“处理”显示为字符。 |
Boolean | 1 | 8 | 系统分配一个字节,但是实际只占用8/1个字节 | true 真 和 false 假。 |
类型转换:
char--> 自动转换:byte-->short-->int-->long-->float-->double
强制转换:①会损失精度,产生误差,小数点以后的数字全部舍弃。②容易超过取值范围。
10、进制?进制之间的转换?
答:
二进制:二进制,Binary,是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”。
计算机中的二进制则是一个非常微小的开关,用“开”来表示1,“关”来表示0。
八进制:八进制,Octal,缩写OCT或O,一种以8为基数的计数法,采用0,1,2,3,4,5,6,7八个数字,逢八进1。一些编程语言中常常以数字0开始表明该数字是八进制。
十进制:十进制,Decimal,就是日常生活中用的最多的,如:1,2,3,……100,200,300……。十进制基于位进制和十进位两条原则,即所有的数字都用10个基本的符号表示,满十进一,同时同一个符号在不同位置上所表示的数值不同,符号的位置非常重要。基本符号是0到9十个数字。
十六进制:十六进制(英文名称:Hexadecimal),是计算机中数据的一种表示方法。同我们日常生活中的表示法不一样。它由0-9,A-F组成,字母不区分大小写。与10进制的对应关系是:0-9对应0-9;A-F对应10-15;N进制的数可以用0~(N-1)的数表示,超过9的用字母A-F。
下面就来看看它们之间的转换关系:
十进制转二进制
方法为:十进制数除2取余法,即十进制数除2,余数为权位上的数,得到的商值继续除2,依此步骤继续向下运算直到商为0为止。
二进制转十进制
方法为:把二进制数按权展开、相加即得十进制数。
二进制转八进制
方法为:3位二进制数按权展开相加得到1位八进制数。(注意事项,3位二进制转成八进制是从右到左开始转换,不足时补0)。
八进制转成二进制
方法为:八进制数通过除2取余法,得到二进制数,对每个八进制为3个二进制,不足时在最左边补零。
二进制转十六进制
方法为:与二进制转八进制方法近似,八进制是取三合一,十六进制是取四合一。(注意事项,4位二进制转成十六进制是从右到左开始转换,不足时补0)。
十六进制转二进制
方法为:十六进制数通过除2取余法,得到二进制数,对每个十六进制为4个二进制,不足时在最左边补零。
方法1:除8取余法,即每次将整数部分除以8,余数为该位权上的数,而商继续除以8,余数又为上一个位权上的数,这个步骤一直持续下去,直到商为0为止,最后读数时候,从最后一个余数起,一直到最前面的一个余数。
例:将十进制的(796)D转换为八进制的步骤如下:
1. 将商796除以8,商99余数为4;
2. 将商99除以8,商12余数为3;
3. 将商12除以8,商1余数为4;
4. 将商1除以8,商0余数为1;
5. 读数,因为最后一位是经过多次除以8才得到的,因此它是最高位,读数字从最后的余数向前读,1434,即(796)D=(1434)O
方法2:使用间接法,先将十进制转换成二进制,然后将二进制又转换成八进制;
十进制转八进制或者十六进制有两种方法
第一:间接法—把十进制转成二进制,然后再由二进制转成八进制或者十六进制。这里不再做图片用法解释。
第二:直接法—把十进制转八进制或者十六进制按照除8或者16取余,直到商为0为止。
八进制或者十六进制转成十进制
方法为:把八进制、十六进制数按权展开、相加即得十进制数。
八进制 >十六进制
方法:将八进制转换为二进制,然后再将二进制转换为十六进制,小数点位置不变。
例:将八进制的(327)O转换为十六进制的步骤如下:
1. 3 = 011;
2. 2 = 010;
3. 7 = 111;
4. 0111 = 7;
5. 1101 = D;
6. 读数,读数从高位到低位,D7,即(327)O=(D7)H。
十六进制 >八进制
方法:将十六进制转换为二进制,然后再将二进制转换为八进制,小数点位置不变。
例:将十六进制的(D7)H转换为八进制的步骤如下:
1. 7 = 0111;
2. D = 1101;
3. 0111 = 7;
4. 010 = 2;
5. 011 = 3;
6. 读数,读数从高位到低位,327,即(D7)H=(327)O。
相互转换详细:
http://www.360doc.com/content/17/0227/22/8067272_632545159.shtml
11、原码、补码、反码?
答:正数的反码和补码都与原码相同。
负数的反码为对该数的原码除符号位外各位取反。
负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1
12、运算符?
答:算术运算符:+ - * / %
赋值运算符:=
比较运算符(关系运算符):> >= < <= != ==
逻辑运算符:
位运算符
深入了解位运算:
===========================================================================
在Java中存在着这样一类操作符,是针对二进制进行操作的。它们各自是&、|、^、~、>>、<<、>>>几个位操作符。不管是初始值是依照何种进制,都会换算成二进制进行位
操作。接下来对这几种操作符进行一下简单的解说。
&:
作用是对运算符两側以二进制表达的操作符按位分别进行'与'运算。而这一运算是以数中同样的位(bit)为单位的。操作的规则是:仅当两个操作数都为1时。输出结果才为1。否
则为0,示比例如以下:
12 的二进制为 1100
5 的二进制为 0101
则 12 & 5 的二进制为 0100,则完整的运算式为 12 & 5 = 4;
|:
作用是对运算符两側以二进制表达的操作符按位分别进行'或'运算。而这一运算是以数中同样的位(bit)为单位的。
操作的规则是:仅当两个操作数都为0时,输出的结果才为0。
否则为1,示比例如以下:
12 的二进制为 1100
5 的二进制为 0101
则 12 | 5 的二进制为 1101。则完整的运算式为 12 & 5 = 13;
^:
作用是对运算符两側以二进制表达的操作数按位分别进行'异或'运算,而这一运算是以数中同样的位(bit)为单位的。
异或运算操作的规则是:仅当两个操作数不同的时候。对应的
输出结果才为1,否则为0,示比例如以下:
12 的二进制为 1100
5 的二进制为 0101
则 12 | 5 的二进制为 1001。则完整的运算式为 12 & 5 = 9;
~:
'取反'运算符~的作用是将各位数字取反:全部的0置为1,1置为0,示比例如以下:
12 的二进制为 1100
进行取反操作为 10000000 00000000 00000000 00001101
则完整的运算式为
~12 = -13
<<:
左移就是把一个数的全部位数都向左移动若干位,示比例如以下:
12 的二进制为 1100
则 12 << 1 的二进制为 11000, 左移是在数的右边补0;则完整的运算式为 12 << 1 = 24;
>>:
右移就是把一个数的全部位数都向右移动若干位,示比例如以下:
12 的二进制为 1100
则 12 >> 1 的二进制为 0110。右移是在数的左边补0; 则完整的运算式为 12 >> 1 = 6;
>>>:
无符号右移一位。不足的补0。 示比例如以下:
12 的二进制为 1100
则 12 >> >1 的二进制为 0110, 则完整的运算式为 12 >> 1 = 6;
详细见:https://www.cnblogs.com/gavanwanggw/p/7015620.html
=======================================================
三元运算符
13、Switch中表达式能放的数据类型有哪些?
答:java 1.6(包括)以前,在switch(expr1)中,expr1只能是一个整数表达式或者枚举常量,整数表达式可以是int基本类型或Integer包装类型,由于,byte,short,char都可以隐式转换为int,所以,这些类型以及这些类型的包装类型也是可以的。显然,long和String类型都不符合switch的语法规定,并且不能被隐式转换成int类型,所以,它们不能作用于swtich语句中。 1.7加入的新特性可以支持String类型的数据。
注:支持String类型的原理:
http://blog.csdn.net/queenjade/article/details/44778653
原来用在 switch 语句中的字符串被替换成了对应的哈希值,而 case 子句的值也被换成了原来字符串常量的哈希值。经过这样的转换,Java 虚拟机所看到的仍然是与整数类型兼容的类型。在这里值得注意的是,在 case 子句对应的语句块中仍然需要使用 String 的 equals 方法来进行字符串比较。这是因为哈希函数在映射的时候可能存在冲突,多个字符串的哈希值可能是一样的。进行字符串比较是为了保证转换之后的代码逻辑与之前完全一样。
14、For循环、while循环、do while循环的区别?
答:while()加循环条件,一但条件不满足就不执行语句。
do-while(),判断条件满足则执行语句,条件不满足时退出循环,但是do-while()是先做再判断,所以至少要做一次循环。
for(定义循环初始条件;循环退出条件;参数自加)。
15、数组的声明?
答:这里以int类型的为例:
第一种:特殊初始化,不用new关键字完成,在数组声明的同时完成初始化操作,也被称其为静态初始化。主要原因是因为采用这种初始化的方式,数组的存储空间的分配是由编译器完成的。
int[] a = {1,2,3};
第二种:先使用new关键字创建数组,然后再分别为数组中的元素赋值,完成初始化操作。(注:如果数组元素类型为基本数据类型,在完成new 操作之后,数组中的元素会自动初始化为空值,可以直接使用,但是数组元素为引用类型,在完成new操作之后,没有给引用类型赋值,就直接使用数组中的元素,会产生运行时异常。)
int[] a = new int[2]; //需要指定数组的长度
第三种:使用new关键字创建数组,同时为数组中的元素赋值,完成出事化操作。
int[] a = new int[]{1,2,3}; //与第二种方法不同,这里new不需要指定数组的长度,数组长度由其后的初始化操作确定
16、数组对应八大基本数据类型的默认值是?
答:Java定义了8个简单的数据类型:字节型(byte),短整型(short),整型(int),长整型(long),字符型(char),浮点型(float),双精度型(double),布尔型(boolean).
除了boolean默认false,char--〉/u0000,其他的都为0。
17、数组有length属性,String有length()方法。
18、常见的排序?(冒泡,选择,快速排序方法)
答:
19、Arrays工具类的使用?
答:
详细见:https://www.cnblogs.com/xing901022/p/6224290.html
三、面向对象
20、java面向对象的三大特性?
答:
1)、面向对象
面向对象是一种程序设计思想,计算机程序的设计实质上就是将现实中的一些事物的特征抽离出来描述成一些计算机事件的过程,这种抽象的过程中,我们把具体的事物封装成一个一个的整体进行描述,使被描述的对象具备一些系统性、整体性的的行为和特征,我们把这种设计思想称为面向对象。
2)、面向对象与面向过程
2.1)、面向过程是早期的程序语言设计思想,该思想强调事物的行为细节,即程序的设计不需要封装成一个个的整体,而是将整个程序描述成一个行为,所有行为细节都按照固定方式一步一步的执行,执行程序就是执行某一行为的过程。
2.2)、面向对象和面向过程都是一种思想,面向对象是相对于面向过程而言的,
面向过程强调的是具体的功能行为,而面向对象将功能封装进对象,强调具备了功能的对象,面向对象是基于面向过程的,但面向对象思想更接近于现实场景。
三大特性
封装和继承几乎都是为多态而准备的
一)、 封装
首先,属性能够描述事物的特征,方法能够描述事物的动作。封装就是把同一类事物的共性(包括属性和方法)归到同一类中,方便使用。
封装:封装也称信息隐藏,是指利用抽象数据类型把数据和基于数据的操作封装起来,使其成为一个不可分割的整体,数据隐藏在抽象数据内部,尽可能的隐藏数据细节,只保留一些接口使其与外界发生联系。也就是说用户无需知道内部的数据和方法的具体实现细节,只需根据留在外部的接口进行操作就行。
封装的好处:
1) 实现了专业的分工
2) 良好的封装能够减少耦合
3) 类内部的结构能够自有修改
4) 可以对成员进行更精确的控制
5) 隐藏信息,实现细节
封装的步骤
1) 修改属性的可见性来限制对属性的访问
2) 为每个属性创建一队赋值和取值方法,用于对这些属性的访问
3) 在赋值和取值方法中,加入对属性的存取限制
为了实现良好的封装,我们通常将类的成员变量声明为private,在通过public方法来对这个变量来访问。对一个变量的操作,一般有读取和赋值2个操作,,我们分别定义2个方法来实现这2个操作,一个是getXX(XX表示要访问的成员变量的名字)用来读取这个成员变量,另一个是setXX()用来对这个变量赋值。
二)、 继承
1. Java继承
Java继承是面向对象的最显著的一个特征。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。JAVA不支持多继承,单继承使JAVA的继承关系很简单,一个类只能有一个父类,易于管理程序,父类是子类的一般化,子类是父类的特化(具体化)
继承所表达的就是一种对象类之间的相交关系,它使得某类对象可以继承另外一类对象的数据成员和成员方法。若类B继承类A,则属于B的对象便具有类A的全部或部分性质(数据属性)和功能(操作),我们称被继承的类A为基类、父类或超类,而称继承类B为A的派生类或子类。
继承避免了对一般类和特殊类之间共同特征进行的重复描述。同时,通过继承可以清晰地表达每一项共同特征所适应的概念范围——在一般类中定义的属性和操作适应于这个类本身以及它以下的每一层特殊类的全部对象。运用继承原则使得系统模型比较简练也比较清晰。
2. Java继承的特征
1) 继承关系是传递的。若类C继承类B,类B继承类A(多继承),则类C既有从类B那里继承下来的属性与方法,也有从类A那里继承下来的属性与方法,还可以有自己新定义的属性和方法。继承来的属性和方法尽管是隐式的,但仍是类C的属性和方法。
2) 继承提供了软件复用功能。若类B继承类A,那么建立类B时只需要再描述与基类(类A)不同的少量特征(数据成员和成员方法)即可。这种做法能减小代码和数据的冗余度,大大增加程序的重用性。
3) 继承通过增强一致性来减少模块间的接口和界面,大大增加了程序的易维护性。
继承的作用:
(1)父类具备的方法子类可以直接继承过来,不用重新书写,提高了代码的复用性
(2)让类与类之间产生关系,有了关系才有多态的实现
(3)Java中只支持单继承,不支持多继承,因为多继承存在安全隐患(当多个父类存在同个功能时,子类不确定要运行哪一个),Java支持多层继承,即父类还可以继承其他类,java用另一种机制解决单继承的局限性,即多实现
继承的特点
覆盖(重写)
如果子父类中的成员一致时,子类成员会覆盖父类成员
当子类继承父类时,沿袭父类的功能到子类中,但子类对该功能的实现细节不一致,子类可以保留父类对该功能的定义,重写功能的内容
覆盖与重载:重载只看参数列表,其他一致参数列表不一致为重载,而重写子父类的参数必须要一致
this与super
this表示当前对象的引用,super表示当前对象父类的引用
子父类中的构造函数
构造函数不能重写
构造函数第一行有一条隐式的语句super()/this()
在对子类对象进行初始化时,父类构造函数也会运行,因为子类中的构造函数默认第一行有一条隐式的super()语句,这样方便子类构造时先获取到父类的共性属性
super()一定要定义在子类构造函数的第一行,当没有默认的空参数构造函数,要手动指定
注意事项:
千万别为了获取其他类中的功能而继承,必须是类与类间有所属关系才可以继承。
子类覆盖父类时必须保证子类权限大于等于父类,才可以覆盖,否则编译失败
子类静态成员只能覆盖父类静态成员
final关键字
final关键字可以修饰类、函数和变量
被final修饰的类不可以被继承(继承打破了封装性)
被final修饰的方法不可以被复写
被final修饰的变量只能被赋值一次,既可以修饰成员变量,也可以修饰
Object类
java中有一个特殊的类,Object类,它是所有对象的超类(根类),Object类中定义了所有对象的共性成员
Object类中的方法
equals() 比较两个对象是否相同
toString() 返回该对象的字符串表示形式
getClass() 获取该对象对应的字节码文件对象
hasCode() 获取该对象的哈希码值
类间的体系关系
继承、聚集(聚合)、组合
继承:
指的是一个类继承另外的一个类的功能,并增加它自己的新功能或改写旧有功能的具体实现,继承是类与类之间最常见的关系。
聚合:
指的是整体与部分的关系。通常在定义一个整体类后,再去分析这个整体类的组成结构。从而找出一些组成类,该整体类和组成类之间就形成了聚合关系。例如足球队中的足球队员就是聚合关系。
组合:
也表示类之间整体和部分的关系,但是组合关系中部分和整体具有统一的生存期。一旦整体对象不存在,部分对象也将不存在。部分对象与整体对象之间具有共生死的关系。例如人的各个身体器官之间的关系。
三)、 多态
方法的重写、重载与动态连接构成多态性;
Java之所以引入多态的概念,原因之一是它在类的继承问题上和C++不同,后者允许多继承,这确实给其带来的非常强大的功能,但是复杂的继承关系也给C++开发者带来了更大的麻烦,为了规避风险,Java只允许单继承,派生类与基类间有IS-A的关系(即“猫”is a “动物”)。这样做虽然保证了继承关系的简单明了,但是势必在功能上有很大的限制,所以,Java引入了多态性的概念以弥补这点的不足,此外,抽象类和接口也是解决单继承规定限制的重要手段。同时,多态也是面向对象编程的精髓所在。
要理解多态性,首先要知道什么是“向上转型”。
我定义了一个子类Cat,它继承了Animal类,那么后者就是前者的父类。我可以通过
Cat c = new Cat(); 例化一个Cat的对象,这个不难理解。
但当我这样定义时: Animal a = new Cat();
这代表什么意思呢?
很简单,它表示我定义了一个Animal类型的引用,指向新建的Cat类型的对象。由于Cat是继承自它的父类Animal,所以Animal类型的引用是可以指向Cat类型的对象的。那么这样做有什么意义呢?因为子类是对父类的一个改进和扩充,所以一般子类在功能上较父类更强大,属性较父类更独特,定义一个父类类型的引用指向一个子类的对象既可以使用子类强大的功能,又可以抽取父类的共性。所以,
父类引用只能调用父类中存在的方法和属性,不能调用子类的扩展部分;因为父类引用指向的是堆中子类对象继承的父类;(但是如果强制把超类转换成子类的话,就可以调用子类中新添加而超类没有的方法了。)
同时,父类中的一个方法只有在父类中定义而在子类中没有重写的情况下,才可以被父类类型的引用调用;
对于父类中定义的方法,如果子类中重写了该方法,那么父类类型的引用将会调用子类中的这个方法,这就是动态连接。
21、类与对象的关系?
答:对象:是具体的事物。
类:是对对象的抽象。
先有具体的对象,然后抽象各个对象之间象的部分,归纳出来类,通过类再认识其他对象。
对象是类的实例化。将对象的公有的功能和属性抽象出来成为一类的具有普遍行为和属性的类。
22、类的组成部分?
答:成员变量、成员方法、构造器、代码块
23、重载与重写的区别?
答:
重载是方法名相同,但形参不同(形参个数或者形参类型),与方法的修饰符与返回值类型无关。它是在一个类中,而重写是在一个子类中,因为重写的前提是要有继承。
24、四种访问修饰符?
答:
25、内部类?
答:
Java中的内部类共分为四种:
静态内部类static inner class (also called nested class)
成员内部类member inner class
局部内部类local inner class
匿名内部类anonymous inner class
静态内部类Static Inner Class
最简单的内部类形式。
类定义时加上static关键字。
不能和外部类有相同的名字。
被编译成一个完全独立的.class文件,名称为OuterClass$InnerClass.class的形式。
只可以访问外部类的静态成员和静态方法,包括了私有的静态成员和方法。
生成静态内部类对象的方式为:
OuterClass.InnerClass inner = new OuterClass.InnerClass();
成员内部类 Member Inner Class
成员内部类也是定义在另一个类中,但是定义时不用static修饰。
成员内部类和静态内部类可以类比为非静态的成员变量和静态的成员变量。
成员内部类就像一个实例变量。
它可以访问它的外部类的所有成员变量和方法,不管是静态的还是非静态的都可以。
在外部类里面创建成员内部类的实例:
this.new Innerclass();
在外部类之外创建内部类的实例:
(new Outerclass()).new Innerclass();
在内部类里访问外部类的成员:
Outerclass.this.member
方法内部类 Local Inner Class
匿名内部类Anonymous Inner Class
匿名内部类就是没有名字的局部内部类,不使用关键字class, extends, implements, 没有构造方法。
匿名内部类隐式地继承了一个父类或者实现了一个接口。
匿名内部类使用得比较多,通常是作为一个方法参数。
生成的.class文件中,匿名类会生成OuterClass$1.class文件,数字根据是第几个匿名类而类推。
26、接口与抽象类的区别?
27、this关键字?
答:this表示当前对象的引用,super表示当前对象父类的引用
This可以修饰方法、属性或构造器。
28、super关键字?
答:this表示当前对象的引用,super表示当前对象父类的引用
Super对父类方法、属性或构造器的引用。
29、Static关键字?
30、什么是值传递,什么是引用传递?
答:
31、是否可以在static环境中访问非static变量或方法?
答:不能。
32、什么是自动拆箱跟自动装箱?
答:
33、java中,什么是构造函数?什么是构造函数重载?什么是复制构造函数?构造函数能否被重写?
答:当新对象被创建的时候,构造函数会被调用。每一个类都有构造函数。在程序员没有给类提供构造函数的情况下,Java编译器会为这个类创建一个默认的构造函数。
Java中构造函数重载和方法重载很相似。可以为一个类创建多个构造函数。每一个构造函数必须有它自己唯一的参数列表。
Java不支持像C++中那样的复制构造函数,这个不同点是因为如果你不自己写构造函数的情况下,Java不会创建默认的复制构造函数。
不能被重写,但是能被重载,因为构造器不能被继承。