Java基础大纲

编程知识 更新时间:2023-05-02 01:36:55

java语法及分类

  • java基础常识
    • 概述
    • 基本语法
    • 数据类型
    • 控制语句
    • 方法
    • 面向对象
    • 面向对象相关内容
    • 数组
    • 相关
    • 异常
    • 集合
    • I/0流
    • 多线程
    • 反射
    • 注解
    • 琐碎知识点

java基础常识

你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

概述

  1. java特点
    1)面向对象:看名字它是注重对象的。当解决一个问题的时候,面向对象会把事物抽象成对象的概念,就是说这个问题里面有哪些对象,然后给对象赋一些属性和方法,然后让每个对象去执行自己的方法,问题得到解决。(面向过程:从名字可以看出它是注重过程的。当解决一个问题的时候,面向过程会把事情拆分成: 一个个函数和数据(用于方法的参数) 。然后按照一定的顺序,执行完这些方法(每个方法看作一个过程),等方法执行完了,事情就搞定了。)

    2)平台移植性:java语言只要编写一次,可以做到到处运行。例如:java程序编写完之后,可以运行在windows操作系统上,不需要做任何改动可以直接运行在Linux操作系统上,同样也 可以运行到MaC OS上面。 一次编写,到处运行。(平台改变了,程序不需要改。) JVM(把程序代码翻译成对应程序可以理解的代码)这种机制实现了跨平台,那么这种机制优点和缺点分别是什么?
    优点:一次编写到处运行,可以跨平台。
    缺点:麻烦。对于运行java程序来说必须先有一个JVM。
    就像你要想在网页上看视频,你必须先安装一个flash是一样的。

    3)简单性,安全性:在Java语言当中真正操作内存的是:JVM(Java虚拟机) 所有的java程序都是运行在Java虚拟机当中的。 而Java虚拟机执行过程中再去操作内存。 对于C或者C++来说程序员都是可以直接通过指针操作内存的。 C或者C++更灵活,可以直接程序员操作内存,但是要求程序员技术精湛。C语言或者C++更有驾驭感。 Java语言屏蔽了指针概念,程序员不能直接操作指针,或者说程序员
    不能直接操作内存。这种方式有优点也有缺点:
    优点:不容易导致内存泄漏。(简单了。)
    缺点:效率问题,包括驾驭感比较差。

    4)多线程:java完全/完美支持多线程并发

    5)健壮性: 主要是因为Java中有一种机制: 自动垃圾回收机制(GC机制)。 java语言是健壮的,相对于C语言来说,C语言没有Java健壮。Java不容易导致内存的泄漏。 C++或者C语言使用不当时很容易导致内存泄漏。JVM负责调度GC机制。程序员不需要干涉。以上讲解中又描述了这几个术语:JVM(C++语言写的一个虚拟的计算机)、GC(垃圾回收机制)

  2. 术语
    1)jdk:Java开发工具箱
    2)jre:java运行环境
    3)jvm:java虚拟机

    JDK包括JRE,JRE包括JVM。JVM是不能独立安装的。JRE和JDK都是可以独立安装的。有单独的JDK安装包。也有单独的JRE安装包。 没有单独的JVM安装包。安装JDK的时候:JRE就自动安装了,同时JRE内部的JVM也就自动安装了。 安装JRE的时候:JVM也就自动安装了。

    问题:
    假设你在软件公司开发了一个新的软件,现在要去客户那边给客户把项目部署一下,把项目跑起来,你需要安装JDK吗?只需要安装JRE就行了。JRE体积很小,安装非常便捷快速。

    问题:
    为什么安装JDK的时候会自带一个JRE? 因为java程序员开发完程序之后,要测试这个程序,让这个程序运行起来,需要JRE。所以JDK安装的时候内部自带一个JRE。

  3. 大致执行过程
    java程序非常重要的两个阶段:
    编译阶段
    运行阶段

注意:java程序员直接编写的java代码(普通文本)是无法执行被JVM 识别的。java程序员编写的java代码这种普通文本必须经过一个编译,将这个“普通文本代码”变成“字节码”,JVM能够识别“字节码”。 java代码这种普通文本变成字节码的过程,被称为:编译。 java代码这种普通文本被称为:java源代码。(你编写的代码是源代码)源代码不能直接执行,需要先进行编译,生成源代码对应的“字节码”JVM可以识别的是字节码。

编译阶段和运行阶段可以在不同的操作系统上完成吗?
在windows上编译 编译之后生成了“字节码”,把“字节码”放到linux上运行,完全可以,因为Java是跨平台的。可以做到一次编写到处运行。

java源代码一旦编译之后,源代码可以删除吗?只留下字节码可以执行吗?
完全可以执行,因为源代码不参与程序的执行过程。 参与程序执行过程的是字节码。 但是最好不要删除源代码。因为有可能执行结果不是你需要的,当执行结果不是你需要的时候,你可以重新打开源代码进行修改,然后重新编译生成新的字节码,再重新执行。这样会有新的执行效果。

放源代码的文件扩展名必须是:xxx.java,并且需要注意的是:编译生成的字节码文件扩展名是:xxx.class
.java文件就是源文件,这个文件中编写源代码。.class文件就是字节码文件,这个文件是编译源代码而得到的。另外需要注意的是:1个java源文件是可以编译生成多个class文件的。 最终运行的是class文件。

问题:字节码文件是二进制文件吗?字节码文件不是二进制文件。 如果是二进制的话,就不需要JVM了。 因为操作系统可以直接执行二进制。 java程序从开发到最终运行经历了什么?
编译期:(可以在windows上)
第一步:在硬盘的某个位置(随意),新建一个xxx.java文件
第二步:使用记事本或者其它文本编辑器例如idea打开xxx.java文件
第三步:在xxx.java文件中编写“符合java语法规则的”源代码。
第四步:保存(一定要将xxx.java文件保存一下)
第五步:使用编译器(javac【JDK安装后自带】)对xxx.java文件进行编译。
第六步:如果xxx.java文件中编写的源代码是符合语法规则的,编译会通过,如果xxx.java文件中编写的源代码违背了语法规则,那么编译器会报错,编译器 报错之后class文件是不会生成的,只有编译通过了才会生成class字节码文件。并且一个java源文件是可以生成多个class文件的。(编译实质上是检查语法)

运行期(JRE在起作用):(可以在windows上,也可以在其他的OS上。)
第七步:如果是在Linux上运行,需要将windows上生成的class文件拷贝过去 不需要拷贝源代码,真正运行的是字节码。(但是源代码也不要删除,有用)
第八步:使用JDK自带的一个命令/工具:java(负责运行的命令/工具)执行字节码
第九步:往下的步骤就全部交给JVM了,就不需要程序员干涉了。JVM会将字节码文件装载进去,然后JVM对字节码进行解释(解释器负责将字节码解释为1010101010…等的二进制)
第十步:JVM会将生成的二进制码交给OS操作系统,操作系统会执行二进制码和硬件进行交互。

注意:在以上的过程中,需要使用两个非常重要的命令?
javac 命令,负责编译
java 命令,负责运行

小插曲:
xxx.java源文件经过编译之后生成了A.class、B.class、C.class等文件, 那么我们称A是一个类、B是一个类、C是一个类。其中A、B、C是类的名字。 没有为什么,死记硬背,SUN公司的java语法就是这么规定的。 A/B/C是类的名称。A类、B类、C类。源文件中编写的代码叫做:源代码。以上是一个复杂的过程,那么缩减一下,程序员到底要干啥?
新建java文件
打开java文件
写java源代码
保存
javac命令编译
java命令运行
编写、编译、运行

  1. Java可以干什么:
    网站后台开发
    Android APP 开发
    大数据开发
    客户端程序(PC 程序)开发
    嵌入式开发

基本语法

1.关键字
在SUN公司开发Java语言的时候,提前定义好了一些具有特殊含义的单词,这些单词全部小写,具有特殊含义,不能用作标识符。java语言中的所有关键字都是全部小写。 注意:java语言中是严格区分大小写的。public和Public不一样。 Class和class不一样。static和Static也不一样。

2.标识符
标识符可以标识什么?
类名、接口名
变量名、方法名
常量名

标识符的命名规则?
标识符只能由数字 字母(可以有中文) 下划线 美元符号组成,不能有其它符号。 标识符不能以数字开始, 标识符严格区分大小写, 关键字不能做标识符, 理论上没有长度限制

标识符的命名规范?
见名知意

驼峰命名方式,一高一低
类名、接口名:首字母大写,后面每个单词首字母大写。
变量名、方法名:首字母小写,后面每个单词首字母大写。
常量名:全部大写,每个单词之间使用下划线衔接。

3.变量
1)字面量就是数据, 数据就是字面量,是一个东西。

2)变量的三要素? 数据类型、变量名、值 (值就是数据,就是字面量。) int i = 100;
到底什么叫做同一个域?????
这个目前不太好解释,大家记住吧:一个大括号代表一个域。
{A域
{B域
{C域
}
}
}
A域包括B域,B域包括C域。

在方法体当中声明的变量叫做局部变量,在方法体外以及类体内声明的变量叫做成员变量。

变量的作用域
出了大括号就不认识了。别的先别管。
{
int i = 100;
{
在这里可以访问i
}
}
{
在这里是无法访问i变量。
}

数据类型

1.数据类型有什么用?
数据类型用来声明变量,程序在运行过程中根据不同的数据类型分配不同大小的空间。
int i = 10;
double d = 1.23;
i变量和d变量类型不同,空间大小不同。

1.2、数据类型在java语言中包括两种:
第一种:基本数据类型
基本数据类型又可以划分为4大类8小种:
第一类:整数型
byte,short,int,long (没有小数的)
第二类:浮点型
float,double (带有小数的)
第三类:布尔型
boolean:只有两个值true和false,true表示真,false表示假
第四类:字符型
char:java中规定字符型字面量必须使用单引号括起来。属于文字。
8小种:
byte,short,int,long
float,double
boolean
char

第二种:引用数据类型
字符串型String属于引用数据类型。
String字符串不属于基本数据类型范畴。
java中除了基本数据类型之外,剩下的都是引用数据类型。
类型 占用字节数量(byte)
------------------------------------
byte 1
short 2
int 4
long 8
float 4
double 8
boolean 1 (1byte的1或0,00000001(true)或00000000(false))
char 2

在类型转换的时候需要遵循哪些规则?
第一条:八种基本数据类型中,除 boolean 类型不能转换,剩下七种类型之间都可以 进行转换;
第二条:如果整数型字面量没有超出 byte,short,char 的取值范围,可以直接将其赋值给byte,short,char 类型的变量;
第三条:小容量向大容量转换称为自动类型转换,容量从小到大的排序为:
byte < short(char) < int < long < float < double,其中 short和 char 都占用两个字节,但是char 可以表示更大的正整数;
第四条:大容量转换成小容量,称为强制类型转换,编写时必须添加“强制类型转换符”, 但运行时可能出现精度损失,谨慎使用;
第五条:byte,short,char 类型混合运算时,先各自转换成 int 类型再做运算;
第六条:多种数据类型混合运算,各自先转换成容量最大的那一种再做运算;

控制语句

控制语句包括几类? 3类: 选择语句 循环语句 转向语句

1)选择语句也可以叫做分支语句
if语句
switch语句

2)循环语句:主要循环反复的去执行某段特定的代码块
for循环
while循环
do…while…循环

3)转向语句
break
continue
return

方法

1)方法是一段可以完成某个特定功能的并且可以被重复利用的代码片段。 方法的出现,让代码具有了很强的复用性。

2)方法重载overload,什么情况下我们考虑使用方法重载机制? 当功能相似的时候,建议将方法名定义为一致的,这样代码美观,又方便编程。 注意:如果功能不相似,坚决要让方法名不一致。代码满足什么条件的时候构成了方法重载? 条件1:在同一个类当中 条件2:方法名相同,条件3:形式参数列表不同(类型、个数、顺序)

3)方法递归、需要理解什么是方法递归? 方法自身调用自身。使用递归的时候,必须添加结束条件,没有结束条件,会发生栈内存溢出错误。StackOverflowError 原因:一直压栈,没有弹栈,栈内存不够用。

面向对象

1.封装,继承,多态
1)封装的代码实现两步:
第一步:属性私有化
第二步:1个属性对外提供两个set和get方法。外部程序只能通过set方法修改,只能通过get方法读取,可以在set方法中设立关卡来保证数据的安全性。在强调一下:set和get方法都是实例方法,不能带static。不带static的方法称为实例方法,实例方法的调用必须先new对象。set和get方法写的时候有严格的规范要求:(大家要按照规矩来)
set方法长这个样子:
public void set+属性名首字母大写(1个参数){
xxx = 1个参数;
}
get方法长这个样子:
public 返回值类型 get+属性名首字母大写(无参){
return xxx;
}
static关键字,static修饰的统一都是静态的,都是类相关的,不需要new对象。直接采用“类名.”访问。当一个属性是类级别的属性,所有对象的这个属性的值是一样的,建议定义为静态变量。
this是一个关键字,是一个引用,保存内存地址指向自身。this可以使用在实例方法中,也可以使用在构造方法中。this出现在实例方法中其实代表的是当前对象。this不能使用在静态方法中。this. 大部分情况下可以省略,但是用来区分局部变量和实例变量的时候不能省略。this() 这种语法只能出现在构造方法第一行,表示当前构造方法调用本类其他的 构造方法,目的是代码复用。
2)继承
继承:在现实世界当中也是存在的,例如:父亲很有钱,儿子不用努力也很有钱。
继承的作用:基本作用:子类继承父类,代码可以得到复用。(这个不是重要的作用,是基本作用。)主要(重要)作用:因为有了继承关系,才有了后期的方法覆盖和多态机制。
java 中的继承只支持单继承,不支持多继承,C++中支持多继承,虽然 java 中不支持多继承,但有的时候会产生间接继承的效果,例如:class C extends B,class B extends A,也就是说,C 直接继承 B,其实 C 还间接继承 A。java 中规定,子类继承父类,除构造方法不能继承之外,剩下都可以继承。但是私有的属性无法在子类中直接访问。(父类中private修饰的不能在子类中 直接访问。可以通过间接的手段来访问。)java 中的类没有显示的继承任何类,则默认继承 Object类,Object类是 java 语言提供的根类(老祖宗类),也就是说,一个对象与生俱来就有Object类型中所有的特征。
方法覆盖
什么时候考虑使用方法覆盖?
父类中的方法无法满足子类的业务需求,子类有必要对继承过来的方法进行覆盖。什么条件满足的时候构成方法覆盖?
第一:有继承关系的两个类
第二:具有相同方法名、返回值类型、形式参数列表
第三:访问权限不能更低。
第四:抛出异常不能更多。
关于Object类中toString()方法的覆盖?
toString()方法存在的作用就是:将java对象转换成字符串形式。大多数的java类toString()方法都是需要覆盖的。因为Object类中提供的toString()方法输出的是一个java对象的内存地址。 至于toString()方法具体怎么进行覆盖? 格式可以自己定义,或者听需求的。(听项目要求的。)
方法重载和方法覆盖有什么区别?
方法重载发生在同一个类当中。方法覆盖是发生在具有继承关系的父子类之间。 方法重载是一个类中,方法名相同,参数列表不同。方法覆盖是具有继承关系的父子类,并且重写之后的方法必须和之前的方法一致:方法名一致、参数列表一致、返回值类型一致。
3)多态
向上转型和向下转型的概念。
向上转型:子—>父 (upcasting)又被称为自动类型转换:Animal a = new Cat();
向下转型:父—>子 (downcasting)又被称为强制类型转换:Cat c = (Cat)a; 需要添加强制类型转换符。
什么时候需要向下转型?需要调用或者执行子类对象中特有的方法。必须进行向下转型,才可以调用。
向下转型有风险吗? 容易出现ClassCastException(类型转换异常)
怎么避免这个风险?instanceof运算符,可以在程序运行阶段动态的判断某个引用指向的对象 是否为某一种类型。养成好习惯,向下转型之前一定要使用instanceof运算符进行判断。不管是向上转型还是向下转型,首先他们之间必须有继承关系,这样编译器就不会报错。
什么是多态。多种形态,多种状态,编译和运行有两个不同的状态。 编译期叫做静态绑定。 运行期叫做动态绑定,Animal a = new Cat();
// 编译的时候编译器发现a的类型是Animal,所以编译器会去Animal类中找move()方法
// 找到了,绑定,编译通过。但是运行的时候和底层堆内存当中的实际对象有关
// 真正执行的时候会自动调用“堆内存中真实对象”的相关方法。
a.move();
多态的典型代码:父类型的引用指向子类型的对象。(java中允许这样写代码!!!)
什么时候必须进行向下转型? 调用子类对象上特有的方法时。
多态在开发中的作用是:降低程序的耦合度,提高程序的扩展力。
public class Master{
public void feed(Dog d){}
public void feed(Cat c){}
}以上的代码中表示:Master和Dog以及Cat的关系很紧密(耦合度高)。导致扩展力很差。
public class Master{
public void feed(Pet pet){
pet.eat();
}
}以上的代表中表示:Master和Dog以及Cat的关系就脱离了,Master关注的是Pet类。 这样Master和Dog以及Cat的耦合度就降低了,提高了软件的扩展性。
面向对象的三大特征: 封装、继承、多态 真的是一环扣一环。有了封装,有了这种整体的概念之后。对象和对象之间产生了继承。有了继承之后,才有了方法的覆盖和多态。这里提到了一个软件开发原则:七大原则最基本的原则:OCP(对扩展开放,对修改关闭)目的是:降低程序耦合度,提高程序扩展力。面向抽象编程,不建议面向具体编程。
super关键字 super能出现在实例方法和构造方法中。super的语法是:“super.”、“super()”super不能使用在静态方法中。 super. 大部分情况下是可以省略的。super.什么时候不能省略呢?父类和子类中有同名属性,或者说有同样的方法, 想在子类中访问父类的,super. 不能省略。 super() 只能出现在构造方法第一行,通过当前的构造方法去调用“父类”中的构造方法,目的是:创建子类对象的时候,先初始化父类型特征。
super的使用:
super.属性名 【访问父类的属性】
super.方法名(实参) 【访问父类的方法】
super(实参) 【调用父类的构造方法】

面向对象相关内容

1.final,接口,抽象方类
1)final关键字,final修饰的类无法继承。final修饰的方法无法覆盖。final修饰的变量只能赋一次值。final修饰的引用一旦指向某个对象,则不能再重新指向其它对象,但该引用指向的对象内部的数据是可以修改的。final修饰的实例变量必须手动初始化,不能采用系统默认值。final修饰的实例变量一般和static联合使用,称为常量。public static final double PI = 3.1415926;
抽象类,第一:抽象类怎么定义?在class前添加abstract关键字就行了。第二:抽象类是无法实例化的,无法创建对象的,所以2)抽象类是用来被子类继承的。第三:final和abstract不能联合使用,这两个关键字是对立的。第四:抽象类的子类可以是抽象类。也可以是非抽象类。第五:抽象类虽然无法实例化,但是抽象类有构造方法,这个构造方法是供子类使用的。第六:抽象类中不一定有抽象方法,抽象方法必须出现在抽象类中。 第七:抽象方法怎么定义?
public abstract void doSome();
第八(****五颗星):一个非抽象的类,继承抽象类,必须将抽象类中的抽象方法进行覆盖/重写/实现。
面试题(判断题):java语言中凡是没有方法体的方法都是抽象方法。 不对,错误的。Object类中就有很多方法都没有方法体,都是以“;”结尾的,但他们都不是抽象方法,例如: public native int hashCode(); 这个方法底层调用了C++写的动态链接库程序。前面修饰符列表中没有:abstract。有一个native。表示调用JVM本地程序。
3)接口的基础语法。接口是一种“引用数据类型”。接口是完全抽象的。接口怎么定义:[修饰符列表] interface 接口名{},接口支持多继承。接口中只有常量+抽象方法。接口中所有的元素都是public修饰的,接口中抽象方法的public abstract可以省略。接口中常量的public static final可以省略。接口中方法不能有方法体。
接口在开发中的作用。注意:接口在开发中的作用,类似于多态在开发中的作用。
多态:面向抽象编程,不要面向具体编程。降低程序的耦合度。提高程序的扩展力。
/

public class Master{
public void feed(Dog d){}
public void feed(Cat c){}
//假设又要养其它的宠物,那么这个时候需要再加1个方法。(需要修改代码了)
//这样扩展力太差了,违背了OCP原则(对扩展开放,对修改关闭。)
}
*/
public class Master{
public void feed(Animal a){
// 面向Animal父类编程,父类是比子类更抽象的。
//所以我们叫做面向抽象编程,不要面向具体编程。
//这样程序的扩展力就强。
}
}
我们以后正好要求,面向抽象编程。 面向抽象编程这句话以后可以修改为:面向接口编程。有了接口就有了可插拔。可插拔表示扩展力很强。不是焊接死的。 主板和内存条之间有插槽,这个插槽就是接口,内存条坏了,可以重新 买一个换下来。这叫做高扩展性。(低耦合度。)接口在现实世界中是不是到处都是呢? 笔记本电脑和键盘之间有接口(usb接口,usb接口是不是某个计算机协会制定的协议/规范。) 接口有什么用?扩展性好。可插拔。 接口是一个抽象的概念。
分析:
中午去饭馆吃饭,这个过程中有接口吗? 接口是抽象的。 菜单是一个接口。(菜单上有一个抽象的照片:西红柿炒鸡蛋)谁面向接口调用。(顾客面向菜单点菜,调用接口。) 谁负责实现这个接口。(后台的厨师负责把西红柿鸡蛋做好!是接口的实现者。)这个接口有什么用呢?这个饭馆的“菜单”,让“顾客”和“后厨”解耦合了。顾客不用找后厨,后厨不用找顾客。他们之间完全依靠这个抽象的菜单沟通。总结一句话:三个字“解耦合”,面向接口编程,可以降低程序的耦合度,提高程序的扩展力。符合OCP开发原则。接口的使用离不开多态机制。(接口+多态才可以达到降低耦合度。)接口可以解耦合,解开的是谁和谁的耦合!!! 任何一个接口都有调用者和实现者。接口可以将调用者和实现者解耦合。调用者面向接口调用。实现者面向接口编写实现。以后进行大项目的开发,一般都是将项目分离成一个模块一个模块的,模块和模块之间采用接口衔接。降低耦合度。
抽象类和接口有什么区别?抽象类是半抽象的。 接口是完全抽象的。抽象类中有构造方法。接口中没有构造方法。接口和接口之间支持多继承。类和类之间只能单继承。一个类可以同时实现多个接口。一个抽象类只能继承一个类(单继承)。 接口中只允许出现常量和抽象方法。 这里先透露一个信息: 以后接口使用的比抽象类多。一般抽象类使用的还是少。 接口一般都是对“行为”的抽象。
2.访问控制,和一些方法
访问控制权限都有哪些? 4个。 private 私有, public 公开,protected 受保护,默认
以上的4个访问控制权限:控制的范围是什么?
private 表示私有的,只能在本类中访问
public 表示公开的,在任何位置都可以访问
“默认”表示只能在本类,以及同包下访问。
protected表示只能在本类、同包、子类中访问。
访问控制修饰符 本类 同包 子类 任意位置
---------------------------------------------------------------------------
public 可以 可以 可以 可以
protected 可以 可以 可以 不行
默认 可以 可以 不行 不行
private 可以 不行 不行 不行
范围从大到小排序:public > protected > 默认 > private
访问控制权限修饰符可以修饰什么?
属性(4个都能用)
方法(4个都能用)
类(public和默认能用,其它不行。)
接口(public和默认能用,其它不行。)
什么是API?
应用程序编程接口。(Application Program Interface)
整个JDK的类库就是一个javase的API。
目前为止我们只需要知道这几个方法即可:
protected Object clone() // 负责对象克隆的。
int hashCode() // 获取对象哈希值的一个方法。
boolean equals(Object obj) // 判断两个对象是否相等
String toString() // 将对象转换成字符串形式
protected void finalize() // 垃圾回收器负责调用的方法
toString()方法 以后所有类的toString()方法是需要重写的。 重写规则,越简单越明了就好。System.out.println(引用); 这里会自动调用“引用”的toString()方法。 String类是SUN写的,toString方法已经重写了。
equals()方法 以后所有类的equals方法也需要重写,因为Object中的equals方法比较的是两个对象的内存地址,我们应该比较内容,所以需要重写。 重写规则:自己定,主要看是什么和什么相等时表示两个对象相等。 基本数据类型比较实用:,,,,,对象和对象比较:调用equals方法 String类是SUN编写的,所以String类的equals方法重写了。以后判断两个字符串是否相等,最好不要使用,要调用字符串对象的equals方法。注意:重写equals方法的时候要彻底。
finalize()方法。 这个方法是protected修饰的,在Object类中这个方法的源代码是? protected void finalize() throws Throwable { }

数组

1、数组
1.1、数组的优点和缺点,并且要理解为什么。
第一:空间存储上,内存地址是连续的。
第二:每个元素占用的空间大小相同。
第三:知道首元素的内存地址。
第四:通过下标可以计算出偏移量。
通过一个数学表达式,就可以快速计算出某个下标位置上元素的内存地址,直接通过内存地址定位,效率非常高。
优点:检索效率高。 缺点:随机增删效率较低,数组无法存储大数据量。注意:数组最后一个元素的增删效率不受影响。

数组的拷贝:System.arraycopy()方法的使用
数组有一个特点:长度一旦确定,不可变。
所以数组长度不够的时候,需要扩容,扩容的机制是:新建一个大数组,
将小数组中的数据拷贝到大数组,然后小数组对象被垃圾回收。
常见的算法:
排序算法:
冒泡排序算法
选择排序算法
查找算法:
二分法查找

相关

String类。
1.1、对String在内存存储方面的理解:
第一:字符串一旦创建不可变。
第二:双引号括起来的字符串存储在字符串常量池中。
第三:字符串的比较必须使用equals方法。
第四:String已经重写了toString()和equals()方法。
1.2、String的构造方法。
String s = “abc”;
String s = new String(“abc”);
String s = new String(byte数组);
String s = new String(byte数组, 起始下标, 长度);
String s = new String(char数组);
String s = new String(char数组, 起始下标, 长度);
StringBuffer/StringBuilder
2.1、StringBuffer/StringBuilder可以看做可变长度字符串。
2.2、StringBuffer/StringBuilder初始化容量16.
2.3、StringBuffer/StringBuilder是完成字符串拼接操作的,方法名:append
2.4、StringBuffer是线程安全的。StringBuilder是非线程安全的。
2.5、频繁进行字符串拼接不建议使用“+”
3.1、包装类存在有什么用?
方便编程。
3.2、八种包装类的类名是什么?
Byte
Short
Integer
Long
Float
Double
Boolean
Character
3.3、所有数字的父类Number
什么是自动装箱和自动拆箱,代码怎么写?
Integer x = 100; // x里面并不是保存100,保存的是100这个对象的内存地址。
Integer y = 100;
System.out.println(x == y); // true
Integer x = 128;
Integer y = 128;
System.out.println(x == y); // false
解析
Integer类常用方法。Integer.valueOf(),, Integer.parseInt(“123”),, Integer.parseInt(“中文”) : NumberFormatException
、Integer String int三种类型互相转换。



2、日期类
2.1、获取系统当前时间
Date d = new Date();
2.2、日期格式化:Date --> String
yyyy-MM-dd HH:mm:ss SSS
SimpleDateFormat sdf = new SimpleDate(“yyyy-MM-dd HH:mm:ss SSS”);
String s = sdf.format(new Date());
2.3、String --> Date
SimpleDateFormat sdf = new SimpleDate(“yyyy-MM-dd HH:mm:ss”);
Date d = sdf.parse(“2008-08-08 08:08:08”);
2.4、获取毫秒数
long begin = System.currentTimeMillis();
Date d = new Date(begin - 1000 * 60 * 60 * 24);

3、数字类
3.1、DecimalFormat数字格式化

###,###.## 表示加入千分位,保留两个小数。
###,###.0000 表示加入千分位,保留4个小数,不够补0

3.2、BigDecimal
财务软件中通常使用BigDecimal

4、随机数
4.1、怎么产生int类型随机数。
Random r = new Random();
int i = r.nextInt();
4.2、怎么产生某个范围之内的int类型随机数。
Random r = new Random();
int i = r.nextInt(101); // 产生[0-100]的随机数。

5、枚举
5.1、枚举是一种引用数据类型。
5.2、枚举编译之后也是class文件。
5.3、枚举类型怎么定义?
enum 枚举类型名{
枚举值,枚举值2,枚举值3
}
5.4、当一个方法执行结果超过两种情况,并且是一枚一枚可以列举出来
的时候,建议返回值类型设计为枚举类型。

异常

0、异常处理机制
java中异常的作用是:增强程序健壮性。
java中异常以类和对象的形式存在。
1、java的异常处理机制
1.1、异常在java中以类和对象的形式存在。那么异常的继承结构是怎样的?
Object
Object下有Throwable(可抛出的)
Throwable下有两个分支:Error(不可处理,直接退出JVM)和Exception(可处理的)
Exception下有两个分支:
Exception的直接子类:编译时异常(要求程序员在编写程序阶段必须预先对这些异常进行处理,如果不处理编译器报错,因此得名编译时异常。)。
RuntimeException:运行时异常。(在编写程序阶段程序员可以预先处理,也可以不管,都行。)
详情
1.2、编译时异常和运行时异常,都是发生在运行阶段。编译阶段异常是不会发生的。
编译时异常因为什么而得名?
因为编译时异常必须在编译(编写)阶段预先处理,如果不处理编译器报错,因此得名。 所有异常都是在运行阶段发生的。因为只有程序运行阶段才可以new对象。 因为异常的发生就是new异常对象。

1.3、编译时异常和运行时异常的区别?
编译时异常一般发生的概率比较高。
举个例子:
你看到外面下雨了,倾盆大雨的。你出门之前会预料到:如果不打伞,我可能会生病(生病是一种异常)。 而且这个异常发生的概率很高,所以我们出门之前要拿一把伞。 “拿一把伞”就是对“生病异常”发生之前的一种处理方式。 对于一些发生概率较高的异常,需要在运行之前对其进行预处理。
运行时异常一般发生的概率比较低。
举个例子:
小明走在大街上,可能会被天上的飞机轮子砸到。被飞机轮子砸到也算一种异常。但是这种异常发生概率较低。 在出门之前你没必要提前对这种发生概率较低的异常进行预处理。如果你预处理这种异常,你将活的很累。
假设你在出门之前,你把能够发生的异常都预先处理,你这个人会更加 的安全,但是你这个人活的很累。
假设java中没有对异常进行划分,没有分为:编译时异常和运行时异常, 所有的异常都需要在编写程序阶段对其进行预处理,将是怎样的效果呢? 首先,如果这样的话,程序肯定是绝对的安全的。但是程序员编写程序太累,代码到处都是处理异常 的代码。
1.4、编译时异常还有其他名字:
受检异常:CheckedException
受控异常
1.5、运行时异常还有其它名字:
未受检异常:UnCheckedException
非受控异常
1.6、再次强调:所有异常都是发生在运行阶段的。
1.7、Java语言中对异常的处理包括两种方式:
第一种方式:在方法声明的位置上,使用throws关键字,抛给上一级。
谁调用我,我就抛给谁。抛给上一级。
第二种方式:使用try…catch语句进行异常的捕捉。
这件事发生了,谁也不知道,因为我给抓住了。
举个例子:
我是某集团的一个销售员,因为我的失误,导致公司损失了1000元,
“损失1000元”这可以看做是一个异常发生了。我有两种处理方式,
第一种方式:我把这件事告诉我的领导【异常上抛】
第二种方式:我自己掏腰包把这个钱补上。【异常的捕捉】
思考:
异常发生之后,如果我选择了上抛,抛给了我的调用者,调用者需要
对这个异常继续处理,那么调用者处理这个异常同样有两种处理方式。
详情
详情
1.8、注意:Java中异常发生之后如果一直上抛,最终抛给了main方法,main方法继续
向上抛,抛给了调用者JVM,JVM知道这个异常发生,只有一个结果。终止java程序的执行。



集合

1、集合概述
1.1、什么是集合?有什么用?
数组其实就是一个集合。集合实际上就是一个容器。可以来容纳其它类型的数据。
集合为什么说在开发中使用较多?集合是一个容器,是一个载体,可以一次容纳多个对象。在实际开发中,假设连接数据库,数据库当中有10条记录, 那么假设把这10条记录查询出来,在java程序中会将10条数据封装成10个java对象,然后将10个java对象放到某一个集合当中,将集合传到前端,然后遍历集合,将一个数据一个 数据展现出来。
1.2、集合不能直接存储基本数据类型,另外集合也不能直接存储java对象,集合当中存储的都是java对象的内存地址。(或者说集合中存储的是引用。)
list.add(100); //自动装箱Integer
注意:
集合在java中本身是一个容器,是一个对象。集合中任何时候存储的都是“引用”。
1.3、在java中每一个不同的集合,底层会对应不同的数据结构。往不同的集合中存储元素,等于将数据放到了不同的数据结构当中。什么是数据结构?数据存储的结构就是数据结构。不同的数据结构,数据存储方式不同。例如:数组、二叉树、链表、哈希表…以上这些都是常见的数据结构。
你往集合c1中放数据,可能是放到数组上了。你往集合c2中放数据,可能是放到二叉树上了。… 你使用不同的集合等同于使用了不同的数据结构。
你在java集合这一章节,你需要掌握的不是精通数据结构。java中已经将数据结构实现了,已经写好了这些常用的集合类,你只需要掌握怎么用?在什么情况下选择哪一种合适的集合去使用即可。
new ArrayList(); 创建一个集合,底层是数组。
new LinkedList(); 创建一个集合对象,底层是链表。
new TreeSet(); 创建一个集合对象,底层是二叉树。

1.4、集合在java JDK中哪个包下?
java.util.*;
所有的集合类和集合接口都在java.util包下。
1.5、为了让大家掌握集合这块的内容,最好能将集合的继承结构图背会!!!
1.6、在java中集合分为两大类:
一类是单个方式存储元素:
单个方式存储元素,这一类集合中超级父接口:java.util.Collection;
一类是以键值对儿的方式存储元素
以键值对的方式存储元素,这一类集合中超级父接口:java.util.Map;
2、总结重点:
第一个重点:把集合继承结构图背会。第二个重点:把Collection接口中常用方法测试几遍。第三个重点:把迭代器弄明白。第四个重点:Collection接口中的remove方法和contains方法底层都会调用equals,这个弄明白。
1、List接口中的常用方法。
List是Collection接口的子接口。所以List接口中有一些特有的方法。
void add(int index, Object element)
Object set(int index, Object element)
Object get(int index)
int indexOf(Object o)
int lastIndexOf(Object o)
Object remove(int index)
2、迭代器迭代元素的过程中不能使用集合对象的remove方法删除元素,要使用迭代器Iterator的remove方法来删除元素,防止出现异常:
ConcurrentModificationException
3、ArrayList
ArrayList集合初始化容量10,扩容为原容量1.5倍。底层是数组。数组优点和缺点要能够说出来!另外要注意:ArrayList集合末尾增删元素效率还是可以的。
4、链表数据结构
第一:单向链表和双向链表数据结构要理解。第二:链表数据结构的优点和缺点要能够说出来。
5、Vector:
Vector初始化容量是10. 扩容为原容量的2倍。底层是数组。Vector底层是线程安全的。怎么得到一个线程安全的List:
Collections.synchronizedList(list);
6、JDK5.0新特性:泛型
第一:集合使用泛型来减少向下转型的操作。第二:怎么使用泛型?第三:怎么自定义泛型?
7、JDK5.0新特性:
foreach
对数组怎么遍历?
for(int i : arr){
System.out.println(i);
}
对集合怎么遍历?
for(String s : list){
System.out.println(s);
}
8、JDK8新特性:钻石表达式
List list = new ArrayList<>();类型自动推断!
1、掌握Map接口中常用方法。
2、遍历Map集合的两种方式都要精通。
第一种:获取所有key,遍历每个key,通过key获取value.
第二种:获取Set<Map.Entry>即可,遍历Set集合中的Entry
调用entry.getKey() entry.getValue()
3、了解哈希表数据结构。
4、存放在HashMap集合key部分和HashSet集合中的元素需要同时重写hashCode和equals。
5、HashMap和Hashtable的区别。
HashMap:初始化容量16,扩容2倍。非线程安全,key和value可以为null。
Hashtable,初始化容量11,扩容2倍+1, 线程安全,key和value都不能是null。
6、Properties类的常用两个方法。
setProperty
getProperty
7、了解自平衡二叉树数据结构。 左小右大原则存储。 中序遍历方式。
8、TreeMap的key或者TreeSet集合中的元素要想排序,有两种实现方式:
第一种:实现java.lang.Comparable接口。 第二种:单独编写一个比较器Comparator接口。
9、集合工具类Collections:
synchronizedList方法
sort方法(要求集合中元素实现Comparable接口。)


I/0流

2、IO流,什么是IO?
I : Input
O : Output
通过IO可以完成硬盘文件的读和写。
3、IO流的分类?
有多种分类方式:
一种方式是按照流的方向进行分类:
以内存作为参照物,
往内存中去,叫做输入(Input)。或者叫做读(Read)。
从内存中出来,叫做输出(Output)。或者叫做写(Write)。
另一种方式是按照读取数据方式不同进行分类:有的流是按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制位。 这种流是万能的,什么类型的文件都可以读取。包括:文本文件,图片,声音文件,视频文件等… 假设文件file1.txt,采用字节流的话是这样读的:
a中国bc张三fe
第一次读:一个字节,正好读到’a’
第二次读:一个字节,正好读到’中’字符的一半。
第三次读:一个字节,正好读到’中’字符的另外一半。
有的流是按照字符的方式读取数据的,一次读取一个字符,这种流是为了方便读取普通文本文件而存在的,这种流不能读取:图片、声音、视频等文件。只能读取纯 文本文件,连word文件都无法读取。 假设文件file1.txt,采用字符流的话是这样读的:
a中国bc张三fe
第一次读:'a’字符('a’字符在windows系统中占用1个字节。)
第二次读:'中’字符('中’字符在windows系统中占用2个字节。)
综上所述:流的分类
输入流、输出流
字节流、字符流
4、Java中的IO流都已经写好了,我们程序员不需要关心,我们最主要还是掌握,在java中已经提供了哪些流,每个流的特点是什么,每个流对象上的常用方法有哪些????
java中所有的流都是在:java.io.*;下。
java中主要还是研究:
怎么new流对象。
调用流对象的哪个方法是读,哪个方法是写。
5、java IO流这块有四大家族:
四大家族的首领:
java.io.InputStream 字节输入流
java.io.OutputStream 字节输出流
java.io.Reader 字符输入流
java.io.Writer 字符输出流
四大家族的首领都是抽象类。(abstract class)
所有的流都实现了: java.io.Closeable接口,都是可关闭的,都有close()方法。 流毕竟是一个管道,这个是内存和硬盘之间的通道,用完之后一定要关闭,不然会耗费(占用)很多资源。养成好习惯,用完流一定要关闭。
所有的输出流都实现了:
java.io.Flushable接口,都是可刷新的,都有flush()方法。养成一个好习惯,输出流在最终输出之后,一定要记得flush()刷新一下。这个刷新表示将通道/管道当中剩余未输出的数据 强行输出完(清空管道!)刷新的作用就是清空管道。 注意:如果没有flush()可能会导致丢失数据。
注意:在java中只要“类名”以Stream结尾的都是字节流。以“Reader/Writer”结尾的都是字符流。
6、java.io包下需要掌握的流有16个:
文件专属:
java.io.FileInputStream(掌握)
java.io.FileOutputStream(掌握)
java.io.FileReader
java.io.FileWriter
转换流:(将字节流转换成字符流)
java.io.InputStreamReader
java.io.OutputStreamWriter
缓冲流专属:
java.io.BufferedReader
java.io.BufferedWriter
java.io.BufferedInputStream
java.io.BufferedOutputStream
数据流专属:
java.io.DataInputStream
java.io.DataOutputStream
标准输出流:
java.io.PrintWriter
java.io.PrintStream(掌握)
对象专属流:
java.io.ObjectInputStream(掌握)
java.io.ObjectOutputStream(掌握)
7、java.io.File类。
File类的常用方法。
重点:
参与序列化的类型必须实现java.io.Serializable接口。并且建议将序列化版本号手动的写出来。
private static final long serialVersionUID = 1L;
3、IO + Properties联合使用。
IO流:文件的读和写。Properties:是一个Map集合,key和value都是String类型。

多线程

1、什么是进程?什么是线程?
进程是一个应用程序(1个进程是一个软件)。线程是一个进程中的执行场景/执行单元。 一个进程可以启动多个线程。
2、对于java程序来说,当在DOS命令窗口中输入:
java HelloWorld 回车之后。会先启动JVM,而JVM就是一个进程。JVM再启动一个主线程调用main方法。同时再启动一个垃圾回收线程负责看护,回收垃圾。最起码,现在的java程序中至少有两个线程并发,一个是垃圾回收线程,一个是执行main方法的主线程。
3、进程和线程是什么关系?举个例子
阿里巴巴:进程
马云:阿里巴巴的一个线程
童文红:阿里巴巴的一个线程
京东:进程
强东:京东的一个线程
妹妹:京东的一个线程
进程可以看做是现实生活当中的公司。线程可以看做是公司当中的某个员工。
注意:
进程A和进程B的内存独立不共享。(阿里巴巴和京东资源不会共享的!)
魔兽游戏是一个进程
酷狗音乐是一个进程
这两个进程是独立的,不共享资源。
线程A和线程B呢?
在java语言中:
线程A和线程B,堆内存和方法区内存共享。但是栈内存独立,一个线程一个栈。
假设启动10个线程,会有10个栈空间,每个栈和每个栈之间,互不干扰,各自执行各自的,这就是多线程并发。
火车站,可以看做是一个进程。 火车站中的每一个售票窗口可以看做是一个线程。 我在窗口1购票,你可以在窗口2购票,你不需要等我,我也不需要等你。所以多线程并发可以提高效率。
java中之所以有多线程机制,目的就是为了提高程序的处理效率。
4、思考一个问题:
使用了多线程机制之后,main方法结束,是不是有可能程序也不会结束。main方法结束只是主线程结束了,主栈空了,其它的栈(线程)可能还在压栈弹栈。


5、分析一个问题:对于单核的CPU来说,真的可以做到真正的多线程并发吗?
对于多核的CPU电脑来说,真正的多线程并发是没问题的。 4核CPU表示同一个时间点上,可以真正的有4个进程并发执行。
什么是真正的多线程并发?
t1线程执行t1的。
t2线程执行t2的。
t1不会影响t2,t2也不会影响t1。这叫做真正的多线程并发。
单核的CPU表示只有一个大脑:
不能够做到真正的多线程并发,但是可以做到给人一种“多线程并发”的感觉。 对于单核的CPU来说,在某一个时间点上实际上只能处理一件事情,但是由于 CPU的处理速度极快,多个线程之间频繁切换执行,跟人来的感觉是:多个事情同时在做!!!!!
线程A:播放音乐
线程B:运行魔兽游戏
线程A和线程B频繁切换执行,人类会感觉音乐一直在播放,游戏一直在运行,给我们的感觉是同时并发的。
6.java语言中,实现线程有两种方式,那两种方式呢?
java支持多线程机制。并且java已经将多线程实现了,我们只需要继承就行了。
第一种方式:编写一个类,直接继承java.lang.Thread,重写run方法。
// 定义线程类
public class MyThread extends Thread{
public void run(){

}
}
// 创建线程对象
MyThread t = new MyThread();
// 启动线程。
t.start();

第二种方式:编写一个类,实现java.lang.Runnable接口,实现run方法。
// 定义一个可运行的类
public class MyRunnable implements Runnable {
public void run(){

}
}
// 创建线程对象
Thread t = new Thread(new MyRunnable());
// 启动线程
t.start();
注意:第二种方式实现接口比较常用,因为一个类实现了接口,它还可以去继承其它的类,更灵活。
7、关于线程对象的生命周期?
新建状态
就绪状态
运行状态
阻塞状态
死亡状态
1、(这部分内容属于了解)关于线程的调度

1.1、常见的线程调度模型有哪些?

抢占式调度模型:
那个线程的优先级比较高,抢到的CPU时间片的概率就高一些/多一些。
java采用的就是抢占式调度模型。

均分式调度模型:
平均分配CPU时间片。每个线程占有的CPU时间片时间长度一样。
平均分配,一切平等。
有一些编程语言,线程调度模型采用的是这种方式。

1.2、java中提供了哪些方法是和线程调度有关系的呢?

实例方法:
void setPriority(int newPriority) 设置线程的优先级
int getPriority() 获取线程优先级
最低优先级1
默认优先级是5
最高优先级10
优先级比较高的获取CPU时间片可能会多一些。(但也不完全是,大概率是多的。)

静态方法:
static void yield() 让位方法
暂停当前正在执行的线程对象,并执行其他线程
yield()方法不是阻塞方法。让当前线程让位,让给其它线程使用。
yield()方法的执行会让当前线程从“运行状态”回到“就绪状态”。
注意:在回到就绪之后,有可能还会再次抢到。

实例方法:
void join()
合并线程
class MyThread1 extends Thread {
public void doSome(){
MyThread2 t = new MyThread2();
t.join(); // 当前线程进入阻塞,t线程执行,直到t线程结束。当前线程才可以继续。
}
}

class MyThread2 extends Thread{

        }

2、关于多线程并发环境下,数据的安全问题。

2.1、为什么这个是重点?
以后在开发中,我们的项目都是运行在服务器当中,而服务器已经将线程的定义,线程对象的创建,线程的启动等,都已经实现完了。这些代码我们都不需要编写。

最重要的是:你要知道,你编写的程序需要放到一个 多线程的环境下运行,你更需要关注的是这些数据在多线程并发的环境下是否是安全的。(重点:*****)

2.2、什么时候数据在多线程并发的环境下会存在安全问题呢?
三个条件:
条件1:多线程并发。
条件2:有共享数据。
条件3:共享数据有修改的行为。
满足以上3个条件之后,就会存在线程安全问题。

2.3、怎么解决线程安全问题呢?
当多线程并发的环境下,有共享数据,并且这个数据还会被修改,此时就存在线程安全问题,怎么解决这个问题?线程排队执行。(不能并发)。 用排队执行解决线程安全问题。这种机制被称为:线程同步机制。专业术语叫做:线程同步,实际上就是线程不能并发了,线程必须排队执行。

怎么解决线程安全问题呀?
使用“线程同步机制”。

线程同步就是线程排队了,线程排队了就会牺牲一部分效率,没办法,数据安全第一位,只有数据安全了,我们才可以谈效率。数据不安全,没有效率的事儿。

2.4、说到线程同步这块,涉及到这两个专业术语:

异步编程模型:
线程t1和线程t2,各自执行各自的,t1不管t2,t2不管t1, 谁也不需要等谁,这种编程模型叫做:异步编程模型。 其实就是:多线程并发(效率较高。)
异步就是并发。

同步编程模型:
线程t1和线程t2,在线程t1执行的时候,必须等待t2线程执行
结束,或者说在t2线程执行的时候,必须等待t1线程执行结束,
两个线程之间发生了等待关系,这就是同步编程模型。
效率较低。线程排队执行。

同步就是排队。

3、Java中有三大变量?【重要的内容。】

实例变量:在堆中。

静态变量:在方法区。

局部变量:在栈中。

以上三大变量中:

局部变量永远都不会存在线程安全问题。
因为局部变量不共享。(一个线程一个栈。)
局部变量在栈中。所以局部变量永远都不会共享。

实例变量在堆中,堆只有1个。
静态变量在方法区中,方法区只有1个。
堆和方法区都是多线程共享的,所以可能存在线程安全问题。

局部变量+常量:不会有线程安全问题。
成员变量:可能会有线程安全问题。

4、如果使用局部变量的话:
建议使用:StringBuilder。
因为局部变量不存在线程安全问题。选择StringBuilder。
StringBuffer效率比较低。

ArrayList是非线程安全的。
Vector是线程安全的。
HashMap HashSet是非线程安全的。
Hashtable是线程安全的。

5、总结:
synchronized有三种写法:

第一种:同步代码块
灵活
synchronized(线程共享对象){
同步代码块;
}

第二种:在实例方法上使用synchronized
表示共享对象一定是this
并且同步代码块是整个方法体。

第三种:在静态方法上使用synchronized
表示找类锁。
类锁永远只有1把。
就算创建了100个对象,那类锁也只有一把。

对象锁:1个对象1把锁,100个对象100把锁。

类锁:100个对象,也可能只是1把类锁。

6、聊一聊,我们以后开发中应该怎么解决线程安全问题?

是一上来就选择线程同步吗?synchronized
不是,synchronized会让程序的执行效率降低,用户体验不好。
系统的用户吞吐量降低。用户体验差。在不得已的情况下再选择
线程同步机制。

第一种方案:尽量使用局部变量代替“实例变量和静态变量”。

第二种方案:如果必须是实例变量,那么可以考虑创建多个对象,这样
实例变量的内存就不共享了。(一个线程对应1个对象,100个线程对应100个对象,
对象不共享,就没有数据安全问题了。)

第三种方案:如果不能使用局部变量,对象也不能创建多个,这个时候
就只能选择synchronized了。线程同步机制。

7、线程这块还有那些内容呢?列举一下
7.1、守护线程
7.2、定时器
7.3、实现线程的第三种方式:FutureTask方式,实现Callable接口。(JDK8新特性。)
7.4、关于Object类中的wait和notify方法。(生产者和消费者模式!)
1.1、守护线程
java语言中线程分为两大类:
一类是:用户线程
一类是:守护线程(后台线程)
其中具有代表性的就是:垃圾回收线程(守护线程)。
守护线程的特点:
一般守护线程是一个死循环,所有的用户线程只要结束,守护线程自动结束。
注意:主线程main方法是一个用户线程。
守护线程用在什么地方呢?
每天00:00的时候系统数据自动备份。这个需要使用到定时器,并且我们可以将定时器设置为守护线程。一直在那里看着,每到00:00的时候就备份一次。所有的用户线程如果结束了,守护线程自动退出,没有必要进行数据备份了。
1.2、定时器
定时器的作用:间隔特定的时间,执行特定的程序。 每周要进行银行账户的总账操作。每天要进行数据的备份操作。在实际的开发中,每隔多久执行一段特定的程序,这种需求是很常见的, 那么在java中其实可以采用多种方式实现:
可以使用sleep方法,睡眠,设置睡眠时间,没到这个时间点醒来,执行任务。这种方式是最原始的定时器。(比较low)
在java的类库中已经写好了一个定时器:java.util.Timer,可以直接拿来用。不过,这种方式在目前的开发中也很少用,因为现在有很多高级框架都是支持定时任务的。
在实际的开发中,目前使用较多的是Spring框架中提供的SpringTask框架,这个框架只要进行简单的配置,就可以完成定时器的任务。
1.3、实现线程的第三种方式:实现Callable接口。(JDK8新特性。)
这种方式实现的线程可以获取线程的返回值。之前讲解的那两种方式是无法获取线程返回值的,因为run方法返回void。
思考:
系统委派一个线程去执行一个任务,该线程执行完任务之后,可能会有一个执行结果,我们怎么能拿到这个执行结果呢?使用第三种方式:实现Callable接口方式。
1.4、关于Object类中的wait和notify方法。(生产者和消费者模式!)
第一:wait和notify方法不是线程对象的方法,是java中任何一个java对象 都有的方法,因为这两个方式是Object类中自带的。wait方法和notify方法不是通过线程对象调用,不是这样的:t.wait(),也不是这样的:t.notify()…不对。
第二:wait()方法作用?
Object o = new Object();
o.wait();
表示: 让正在o对象上活动的线程进入等待状态,无期限等待,直到被唤醒为止。o.wait();方法的调用,会让“当前线程(正在o对象上活动的线程)”进入等待状态。
第三:notify()方法作用?
Object o = new Object();
o.notify();
表示:唤醒正在o对象上等待的线程。 还有一个notifyAll()方法:这个方法是唤醒o对象上处于等待的所有线程。

反射

1、反射机制有什么用?
通过java语言中的反射机制可以操作字节码文件。优点类似于黑客。(可以读和修改字节码文件。)通过反射机制可以操作代码片段。(class文件。)
2、反射机制的相关类在哪个包下?
java.lang.reflect.*;
.3、反射机制相关的重要的类有哪些?
java.lang.Class:代表整个字节码,代表一个类型,代表整个类。
java.lang.reflect.Method:代表字节码中的方法字节码。代表类中的方法。
java.lang.reflect.Constructor:代表字节码中的构造方法字节码。代表类中的构造方法
java.lang.reflect.Field:代表字节码中的属性字节码。代表类中的成员变量(静态变量+实例变量)。
java.lang.Class:
public class User{
// Field
int no;
// Constructor
public User(){
}
public User(int no){
this.no = no;
}

// Method
public void setNo(int no){
this.no = no;
}
public int getNo(){
return no;
}
}

3、关于JDK中自带的类加载器:(聊一聊,不需要掌握,知道当然最好!)
3.1、什么是类加载器?
专门负责加载类的命令/工具。
ClassLoader
3.2、JDK中自带了3个类加载器
启动类加载器:rt.jar
扩展类加载器:ext/*.jar
应用类加载器:classpath
3.3、假设有这样一段代码:
String s = “abc”;
代码在开始执行之前,会将所需要类全部加载到JVM当中。通过类加载器加载,看到以上代码类加载器会找String.class 文件,找到就加载,那么是怎么进行加载的呢?
首先通过“启动类加载器”加载。 注意:启动类加载器专门加载:C:\Program Files\Java\jdk1.8.0_101\jre\lib\rt.jar ,rt.jar中都是JDK最核心的类库。如果通过“启动类加载器”加载不到的时候,会通过"扩展类加载器"加载。注意:扩展类加载器专门加载:C:\Program Files\Java\jdk1.8.0_101\jre\lib\ext*.jar,如果“扩展类加载器”没有加载到,那么会通过“应用类加载器”加载。注意:应用类加载器专门加载:classpath中的类。
3.4、java中为了保证类加载的安全,使用了双亲委派机制。 优先从启动类加载器中加载,这个称为“父”, “父”无法加载到,再从扩展类加载器中加载, 这个称为“母”。双亲委派。如果都加载不到,才会考虑从应用类加载器中加载。直到加载到为止。
1.在java中获取Class的三种方式?
第一种:
Class c = Class.forName(“完整类名”);
第二种:
Class c = 对象.getClass();
第三种:
Class c = int.class;
Class c = String.class;
2、获取了Class之后,可以调用无参数构造方法来实例化对象
//c代表的就是日期Date类型
Class c = Class.forName(“java.util.Date”);
//实例化一个Date日期类型的对象
Object obj = c.newInstance();
一定要注意:
newInstance()底层调用的是该类型的无参数构造方法。如果没有这个无参数构造方法会出现"实例化"异常。

3、如果你只想让一个类的“静态代码块”执行的话,你可以怎么做?
Class.forName(“该类的类名”);这样类就加载,类加载的时候,静态代码块执行!!!!在这里,对该方法的返回值不感兴趣,主要是为了使用“类加载”这个动作。
4、关于路径问题?
String path = Thread.currentThread().getContextClassLoader().getResource(“写相对路径,但是这个相对路径从src出发开始找”).getPath();
String path = Thread.currentThread().getContextClassLoader().getResource(“abc”).getPath(); //必须保证src下有abc文件。
String path = Thread.currentThread().getContextClassLoader().getResource(“a/db”).getPath(); //必须保证src下有a目录,a目录下有db文件。
String path = Thread.currentThread().getContextClassLoader().getResource(“com/bjpowernode/test.properties”).getPath();
//必须保证src下有com目录,com目录下有bjpowernode目录。
//bjpowernode目录下有test.properties文件。
这种方式是为了获取一个文件的绝对路径。(通用方式,不会受到环境移植的影响。)但是该文件要求放在类路径下,换句话说:也就是放到src下面。 src下是类的根路径。
直接以流的形式返回:
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(“com/bjpowernode/test.properties”);
5、IO + Properties,怎么快速绑定属性资源文件?
/要求:第一这个文件必须在类路径下
//第二这个文件必须是以.properties结尾。
ResourceBundle bundle = ResourceBundle.getBundle(“com/bjpowernode/test”); String value = bundle.getString(key);
重点
通过反射机制访问对象的某个属性。
通过反射机制调用对象的某个方法。
通过反射机制调用某个构造方法实例化对象。
通过反射机制获取父类以及父类型接口。

注解

1、注解,或者叫做注释类型,英文单词是:Annotation
2、注解Annotation是一种引用数据类型。编译之后也是生成xxx.class文件。
3、怎么自定义注解呢?语法格式?
[修饰符列表] @interface 注解类型名{

}
4、注解怎么使用,用在什么地方?
第一:注解使用时的语法格式是:
@注解类型名
第二:注解可以出现在类上、属性上、方法上、变量上等…
注解还可以出现在注解类型上。
5、JDK内置了哪些注解呢?
java.lang包下的注释类型:
掌握:
Deprecated 用 @Deprecated 注释的程序元素,不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。
掌握:
Override 表示一个方法声明打算重写超类中的另一个方法声明。
6、元注解
什么是元注解?
用来标注“注解类型”的“注解”,称为元注解。
常见的元注解有哪些?
Target
Retention
关于Target注解:
这是一个元注解,用来标注“注解类型”的“注解” 这个Target注解用来标注“被标注的注解”可以出现在哪些位置上。
@Target(ElementType.METHOD):表示“被标注的注解”只能出现在方法上。
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
表示该注解可以出现在:
构造方法上
字段上
局部变量上
方法上

类上…
关于Retention注解:
这是一个元注解,用来标注“注解类型”的“注解”
这个Retention注解用来标注“被标注的注解”最终保存在哪里。
@Retention(RetentionPolicy.SOURCE):表示该注解只被保留在java源文件中。
@Retention(RetentionPolicy.CLASS):表示该注解被保存在class文件中。
@Retention(RetentionPolicy.RUNTIME):表示该注解被保存在class文件中,并且可以被反射机制所读取。
7、Retention的源代码
//元注解
public @interface Retention {
//属性
RetentionPolicy value();
}
RetentionPolicy的源代码:
public enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
//@Retention(value=RetentionPolicy.RUNTIME)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation{}
注解在开发中有什么用呢?
需求:
假设有这样一个注解,叫做:@Id,这个注解只能出现在类上面,当这个类上有这个注解的时候, 要求这个类中必须有一个int类型的id属性。如果没有这个属性就报异常。如果有这个属性则正常执行!

琐碎知识点

javac是一个Java编译器工具/命令。经过javac生成.class文件,运行过程大概是。.java经过语法检查经过.javac编译工具编译成.class字节码文件,交给jvm虚拟机中类加载器,类加载器回去找.class文件解释称010101010,操作系统执行二进制和底层硬件进行交互,jdk目录介绍:jdk/bin:该目录下存放了很多命令,例如:javac.exe和java.exe javac.exe负责编译,,java.exe负责运行

为什么要配置环境变量:打开dos命令,输入javac,回车,若出现javac不是内部和外部命令,出现的原因在于window操作系统无法找到javac命令文件. window操作系统如何搜索某个命令,首先会当前目录下搜索,当前目录搜索不到的话,会从环境变量path指定的路径当中搜索某个命令,如果都搜索不到则会报错。path环境变量和Java语言没有关系,path环境变量是专门给window操作系统指路的,javac要想能够随意使用,需要将javac所在的目录配置到环境变量path当中,path里可以存多个路径,一定要用英文分号隔开。

在dos命令下运行时,先寻找到当前.java的目录下,然后javac.文件名.java,然后Java 文件名(不要后缀) 若失败无法找到,可暂时将package包注释掉,因为Java代码中含有package包了,在dos下无法识别package路径,暂时注释即可。dos命令中 dir全部目录内容,cd 加目录跳到指定目录,cd … 上一个目录,ipconfig ip配置,e: 调换到e盘 cd.当前目录

public class 公开类只能用一个,并且和文件名名称一致

一般整数字面值会被当成int来处理,要用到long 或者float 浮点型,加L,f.大容量不能直接转小容量,需要强制转换,(int),会损失精度,byte b =60.大容量转小容量,按理说不可以,其实不超过byte的取值范围则可以编译通过,超过报错。数据在计算机存储是补码形式。float 4个字节,double 8个字节,但double相对于财务软件来说精度不够。因此准备了更高的类型,只不过这种类型是一种引用数据类型,不属于基本数据类型,它是 java.math.BigDecimal 其实Java程序是sun 提供的一个庞大的类库,Java程序猿是基于这套基础类库来进行开发的,se类库源码在:java\jdk\lib\src.zip java shi是一种强类型语言,通俗来说就是在Java中存储的数据是有类型的而且必须在编译时就确定其类型,Java中有俩类数据类型,基本数据类型和引用数据类型,在Java领域中,基本数据类型变量存的是数据本身,而引用类型变量存储的是保存数据的空间地址。说白了,基本数据类型变量里存储的是直接放在抽屉里的东西,而引用数据类型变量里存储的是这个抽屉里的钥匙,钥匙和抽屉一一对应。引用数据类型建议在基本数据类型的基础之上,包括数组、类(String属于类)、接口、枚举、注解。引用数据类型是由用户自定义,用来限制其他 数据的类型,实际上引用类型变量就是一个指针,只是java语言不在使用这个说法。float d=5.1.会报错,大容量转小容量,有小数点的会以double为准。

小容量向大容量转换,称自动类型转换,容量从小到大,byte<short\char(平级)<int<long<float<double 任何浮点类型不管占多少个字节都比整数容量大,char和short可表示的种类数量相同,但是char可以取更大的正整数,大容量转换小容量叫强制类型转换,需要加强制类型转换符程序才能编译通过,但是运行阶段可能会损失精度,当整数字面值没有超过byte short char 的取值范围,可以直接赋值给byte short char 类的变量 byte short char 混合运算的时候,各自先转换成int类型在做运算。多种数据类型混合运算,先转换成容量最大的那种类型在做运算。

& 逻辑与 俩边都为true 结果才为true | 逻辑或 俩边只要有一个true 结果才为true ! 逻辑非 取反 !false就是true !true就是false 单目运算符 ………^逻辑异或 俩边只要不一样就为true && 短路与 只要一边是false 则不用去计算另一半。 || 短路或 只要一边是true 则不用计算另一半。

super 是一个关键字 全部小写, this 能出现在实例化方法和构造方法中 this 语法是 “this.” 、 “this()”.this 不能使用在静态方法中(static), “this.” 大部分情况下可以省略, “this.”什么时候不能省略,在区分局部变量和实例变量的时候不能省略。public void setName(String name){
this.name=name;
}
this()只能出现在构造方法第一行,通过当前的构造方法去调用“本类”中其他的构造方法,目的是 代码复用。super 能出现在实例化方法和构造方法中 super 的语法是 super. super() super不能使用在静态方法中,super. 大部分情况下可以省略 super()只能出现在构造方法第一行,通过当前的构造方法去调用本类中的构造方法,目的是创建子类对象的时候,先初始化父类型特征 super() 表示通过子类的构造方法去调用父类的构造方法 模拟现实世界中这种场景:要想有儿子,需要先有父亲,重要的结论:当一个构造方法第一行 既没有this() 又没有super()的话,默认会有一个super();表示通过当前子类的构造方法调用父类的无参构造方法,所以必须保证父类的无参数构造方法是存在的 注意:this()和super() 不能共存,他们都是只能出现在构造方法第一行。无论怎么折腾,父类的构造方法一定会执行 在java语言中不管是new什么对象,最后老祖宗的object 类的无参构造方法一定会执行,object类的无参构造方法处于栈顶部,以后写代码的时候,一个类的无参数构造方法还是建议手动的写出来,如果无参数构造方法丢失的话,可能会影响到子类对象的构建。super.在什么时候不能省略,父类和子类中有同名属性,或者说有同样的方法,想在子类中访问父类的,super. 不能省略 super 的使用 super.属性名 访问父类的属性 super.方法名(实参) 访问父类的方法 super(实参)调用父类的构造方法 super就代表父。

什么是抽象类 类和类之间具有共同特征,将这些共同特征提取出来,形成的就是抽象类,类本身是不存在的,所以抽象类无法创建对象(无法实例化) 抽象类属于引用数据类型

【修饰符列表】 abstract class 类名{} 抽象类是无法实例化的,无法创建对象的,所以抽象类是用来被子类继承的。final 和abstract 不能联合使用,这俩个关键字是对立的。抽象类的子类可以是抽象类,也可以是非抽象类,抽象方法表示没有实现的方法,没有方法体的方法 抽象方法的特点 public abstract void dosome(); 没有方法体,以分号结尾,前面修饰符列表中有abstract 关键字 抽象类中不一定有抽象方法,抽象方法必须出现在抽象类中。 一个非抽象的类,继承抽象类,必须将抽象类中的抽象方法进行覆写

接口的基本语法 接口是一种引用数据类型,编译之后也是一个class字节码文件 接口是完全抽象的,或者也可以说接口是特殊的抽象类 接口的定义:【修饰符列表】 interface 接口名{} 接口支持多继承,一个接口可以继承多个接口,接口中只包含俩部分内容,一个是常量,一个是抽象方法,接口中没有其他内容 接口中所有的元素都是public 修饰的 ,都是公开的,接口中的抽象方法定义时,public abstract修饰符可以省略 接口中的方法都是抽象方法,所以接口中的方法不能有方法体 接口中的常量的public static final 可以是省略 一个非抽象的类,实现接口的时候,必须将接口中的所有方法加以实现,一个类可以实现多个接口, extends 和 implements可以共存,extends在前 implements在后, 使用接口,写代码的时候,可以使用多态(父类型引用指向子类型对象)。

抽象类是半抽象的,接口是完全抽象的,抽象类中有构造方法,接口中没有构造方法,接口和接口之间支持多继承,类和类之间只能单继承。一个类可以同时实现多个接口,一个抽象类只能继承一个类(单继承) 接口中允许出现常量和抽象方法,以后接口使用的比抽象类 多,一般抽象类使用的还是少,接口一般都是对行为的抽象。
分析:中午去饭馆吃饭,接口是抽象的,菜单是一个接口 ,菜单上有一个抽象的照片:西红柿炒鸡蛋,谁面向接口调用,顾客面向菜单点菜,调用接口,谁负责实现这个接口,后台的厨师负责把西红柿炒鸡蛋做好,是接口的实现者,这个接口有什么用,这个饭馆的菜单,让顾客和后厨解耦合了,顾客不用找后厨,后厨不用找顾客,他们之间完全依靠这个抽象的菜单沟通,总结一句话三个字姐耦合,面向接口编程,可以降低程序的耦合度,提高程序的扩展力,接口的使用离不开多态机制,接口加多态才可以达到降低耦合度,接口可以解耦合,任何一个接口都有调用者和实现者,接口可以将调用者和实现者解耦合,调用者面向接口调用,实现者面向接口编写实现,以后经行大项目开发,一般都是将项目分离成一个模块一个模块的,模块和模块之间采用接口连接,降低耦合度

1.面向对象和面向过程:面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。性能比面向对象好,因为类调用时需要实例化,开销比较大,比较消耗资源,不易维护,不易复用,不易 扩展,(定制化手枪)

面向对象就是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为(类)。面向对象是模拟化的,你只需抽象出一个类,这是一个封闭的盒子,至于这个功能是如何实现的,不用管,会用就可以,易维护,易复用,易扩展,有封装,继承,多态性的特点,不过性能比面向对象低。(流水线手枪)

2.Javaee企业级开发,javasejava标准版,Javamejava嵌入式开发

3.Java代码的处理过程:.java ->编译->.class->解释->011010…,在解释这一步中是在jvmJava虚拟机上完成解释不同平台上的代码,通过解释器将代码运行(翻译官)

4.jdk java开发工具包(开发工具,和编译器) jre java运行环境(Java虚拟机,Java核心类库,和支持文件)

5.通常情况我们需要配置以下三个变量:

JAVA_HOME:指向Jdk的安装目录,作用是一些基于Java开发的工具会用到,比如tomcat,Eclipse,如果不用这些工具不需要配置。
Path:指向jdk安装目录下的bin目录,作用是指定命令搜索路径,bin目录下有编译、启动(javac/java)等命令,为了任何目录位置下都可以直接输入命令,而不用输入长长的路径了。如果配置了JAVA _HOME ,直接把%JAVA_HOME%/bin追加到PATH中即可。
CLASSPATH:在于告诉Java执行环境,在哪些目录下可以找到我们所要执行的Java程序所需要的类或者包。不过在JDK1.5之后的版本完全可以不用设置classpath环境变量就能正常运行程序。
windows系统下,假如我们安装了某一款软件,安装结束后,在安装目录会生成一个该软件的.exe文件,双击该文件,我们就能启动软件。但是难道我们每次要运行该软件的时候都要先找到该.exe文件所在的路径,然后双击吗,显然是不可能的,因为安装的软件太多,我们根本不可能记住所有已安装软件的路径。这时候就需要环境变量了。

6.面向对象的程序设计有封装性(不必知道细节)继承性(子类,父类),多态性(方法重载:在一个类中,允许多个方法使用同一种名字,但方法的参数不同,完成的功能也不同,对象多态:子类对象可以与父类对象进行转换,而且根据其使用的子类不同完成的功能也不同。

7.类和对象,类相当于抽象概念,对象相当于具体事物,类实际上是对象操作的模板,但类不能够直接使用,必须通过实例化对象来使用(类相当于制作汽车图纸,对象相当于汽车)、类代表一类事物,对象是实际存在的个体,现实世界当中实际存在。

8.类是由属性和方法组成的,属性代表类的状态信息,方法代表类的动作信息
class 类名{
数据类型 属性(变量);
public 返回值的数据类型 方法名称(参数1,参数2.。。){
程序语句;
【return 表达式】;
}

9.关于static 在主类中定义,并且由主方法直接调用的方法必须加static.如果由对象调用的方法定义不加static,如果不是由对象调用的方法才加上static.

10.类是引用数据类型(数组也是),而引用数据类型和基本数据类型最大的不同在于需要内存的开辟及使用,所以关键字new的主要功能是开辟内存空间,只要是引用类型想使用,就必须使用关键字new 开辟空间。堆内存保存每一个对象的属性内容,堆内存需要关键字new开辟,对象没有对应的堆内存将无法使用,栈内存只能保留一块堆内存地址。
static方法不受实例化对象的限制,

11.在开发中,针对属性有这样一中定义:所有在类中定义的属性都要求使用private声明,如果属性被外部所使用,那么按照要求定义相应的setter,getter方法,以String title为例进行说明。setter方法主要是设置内容:public void setTitle(String t),有参;getter方法主要是取得属性内容:public String getTitle(),无参。

12.构造方法:对象实例化时为其进行一些初始化准备操作,是一种特殊的方法,他只在新对象实例化的时候调用,定义原则:方法名称与类名称相同,没有返回值类型声明,构造方法也可以重载。实例化格式:类名称(规定了对象的类型。即对象可以使用哪些属性与方法)对象名称(唯一的标记)=new(开辟新的堆内存空间) 类名称()(调用一个与类名称一样的方法,这就是构造方法)

13.this 可以完成三件事:调用本类属性,调用本类方法,表示当前对象。可以与方法中参数重名区别开。

14.主方法:public :主方法是程序的开始,所以这个方法对任何操作都一定是可见的,static:证明此方法由类名称调用,void:主方法是一切执行的开始点,既然是所以的开头,就不能回头,直到执行完毕为止。main:是一个系统规定好的方法名称,不能修改, String args[]:指的程序运行时传递的参数,格式为:Java 类名称 参数 参数

15在继承中由于super()主要是调用父类的构造方法,所以必须放在子类构造方法的首行。父类提供无参构造方法时,是否编写super()无所谓,父类没有无参构造方法时,要使用super()调用父类指定参数的构造方法。

16.final final定义类,方法和属性,final定义的类不能再有子类,任何类都不能继承以final声明的父类,若定义方法,方法也不能覆写。一般定义常量。

17.对象向上转型(自动完成) (实例化的是子类对象,对象向上转型(父类))对象向下转型(强制,先向上再向下,A a=new B(); B b=(B) a;在实际开发中,对象向上转型的主要意义在于参数的统一,也是最为主要的用法,而对象的向下转型指的是调用子类的个性化操作方法。

18.抽象方法指的是没有方法体的方法,必须以adstract关键字定义,抽象类是不能直接进行对象实例化操作的,要使用抽象类必须遵守抽象类必须有子类,每一个抽象类一定要被子类所继承,java中每个子类只能够继承一个抽象类,所以具备单继承局限,抽象类子类必须覆写抽象类的全部抽象方法(强制子类覆写),依靠对象的向上转型概念,可以通过抽象类的子类完成抽象类的实例化对象操作,

19.接口:接口属于特殊的类,这个类里面只有抽象方法与全局常量 接口有三个原则:接口必须要有子类,但是此时一个子类可以使用implements关键字实现多个接口,避免单继承。接口的子类,必须要覆写接口中的全部抽象方法;接口的对象可以利用子类对象的向上转型进行实例化操作。

20.Object类是所有类的父类,也就是说任何一个类在定义时如果没有明确的继承一个父类,那么它就是Object类的子类。 Object类三个方法覆写 public String toString() ,public boolean equals(Object obj) public int hashCode().

21.1)抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。举个简单的例子,飞机和鸟是不同类的事物,但是它们都有一个共性,就是都会飞。那么在设计的时候,可以将飞机设计为一个类Airplane,将鸟设计为一个类Bird,但是不能将 飞行 这个特性也设计为类,因此它只是一个行为特性,并不是对一类事物的抽象描述。此时可以将 飞行 设计为一个接口Fly,包含方法fly( ),然后Airplane和Bird分别根据自己的需要实现Fly这个接口。然后至于有不同种类的飞机,比如战斗机、民用飞机等直接继承Airplane即可,对于鸟也是类似的,不同种类的鸟直接继承Bird类即可。从这里可以看出,继承是一个 "是不是"的关系,而 接口 实现则是 "有没有"的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比如鸟是否能飞(或者是否具备飞行这个特点),能飞行则可以实现这个接口,不能飞行就不实现这个接口。
  2)设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。什么是模板式设计?最简单例子,大家都用过ppt里面的模板,如果用模板A设计了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A了,如果它们的公共部分需要改动,则只需要改动模板A就可以了,不需要重新对ppt B和ppt C进行改动。而辐射式设计,比如某个电梯都装了某种报警器,一旦要更新报警器,就必须全部更新。也就是说对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动.
  
22.==和equals == 的作用:  基本类型:比较的就是值是否相同  引用类型:比较的就是地址值是否相同equals 的作用:  引用类型:默认情况下,比较的是地址值,重写该方法后比较对象的成员变量值是否相同

更多推荐

Java基础大纲

本文发布于:2023-04-25 01:45:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/71659f923f7b91db062ecf1f96e1bef7.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:大纲   基础   Java

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!

  • 101905文章数
  • 26138阅读数
  • 0评论数