前言
大一的学习生涯已经过了大半学期了,对于所学的java知识也未曾有过整理,借着周末时间整理一下上半学期所学的知识点,一方面可以加深下记忆,一方面忘记了也方便翻阅查找。
java基础概括图
Java概述
java发展概述
Java由SUN公司研发,SUN 被 Oracle 收购
Java 由1995年发布,正式版本由1996年1月发布(jdk1.0)
Java之父: James Gosling
java体系
- javaSE,标准版,各应用平台的基础,桌面开发和低端商务应用的解决方案。
- javaEE,企业版,以企业为环境而开发应用程序的解决方案。
- javaME,微型版,致力于消费产品和嵌入式设备的最佳方案。
java可以做什么
- 开发桌面应用程序。
- 开发面向Internet的web应用程序。
- 提供各行业的解决方案。
- 开发android手机应用程序。
java的特性
- 简单易学: Java语言的语法与C语言和C++语言很接近,使得大多数程序员很容易学习和使用Java。
- 面向对象: Java语言支持封装、继承、多态,面对对象编程,让程序的耦合度更低,内聚性更高。
- 跨平台型:Java语言编写的程序可以运行在各种平台上,也就是说同一段程序既可以在Windows操作系统上运行,也可以在Linx操作系统上运行。
- 解释型:Java程序在Java平台上被编译为字节码格式,然后可以在实现这个Java平台的任何系统的解释器中运行。
- 多线程: Java语言是支持多线程的。所谓多线程可以简单理解为程序中有多个任务可以并发执行,这样可以在很大程度上提高程序的执行效率。
- 健壮型: Java的强类型机制、异常处理、垃圾的自动收集等是Java程序健壮性的重要保证。对指针的丢弃是Java的明智选择。
- 可靠安全: Java语言经常被用在网络环境中,为了增强安全性,Java语言提供了防止恶意代码攻击的安全机制(数组边界检查和bytecode校验等)。
JDK &JRE
JDK:(Java Development Kit Java开发工具包),JDK是提供给Java开发人员使用的,其中包含了java的开发工具,也包括了JRE。其中的开发工具:编译工具(javac.exe) 打包工具(jar.exe)、执行工具(java.exe)等
JRE:(Java Runtime Environment Java运行环境) ,包括Java虚拟机(JVM Java Virtual Machine)和Java程序所需的核心类库等,如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。
Win10下 Java环境变量配置
https://jason.langke01.cn/index.php/archives/31.html 文章单独讲解环境变量配置及JDK下载
java应用程序的运行机制
先编译(.class),在解释运行。
java程序开发的三个步骤
- 编写源程序,java源代码文件。
- 编译源程序,编译器编译编译成java字节码文件。
- 运行,java虚拟机(JVM)。
java是分两部分的:一个是编译,一个是运行
javac:负责的是编译的部分,当执行javac时,会启动java的编译器程序。对指定扩展名的.java文件进行编译。生成了jvm可以识别的字节码文件。也就是class文件,也就是java的运行程序。
java:负责运行的部分.会启动jvm.加载运行时所需的类库,并对class文件进行执行.
一个文件要被执行,必须要有一个执行的起始点,这个起始点就是main函数.
开发java应用的要点
- 一个源文件中只能有一个public修饰的类,其他类个数不限。
- 一个源文件有n个类时,编译结果的class文件就有n个。
- 源文件的名字必须和public修饰的类名相同。
- java语言中单词拼写大小写严格区分。
- main方法入口。
- 每一句以分号(;)结束。
Java文档注释
//单行注释
/*
多行注释:不能嵌套
*//**
文档注释: 可以通过 javadoc -d mydoc -author -version HelloWorld.java 命令生成说明文档
*/
开发工具:
- Eclipse 官网下载地址:https://www.eclipse.org/downloads/
- MyEclipse 官网下载地址:https://www.myeclipsecn.com/
- IntelliJ IDEA 官网下载地址:https://www.jetbrains.com/idea/
java语法基础
标识符
凡是自己命名的地方都叫标识符。 如: 包名、类名、接口名、方法名、变量名、常量名
关键字
Java赋予了特殊含义的单词。
命名的规则
- 可使用 字母 A-Z a-z 数字 0-9 特殊字符 下划线 “_” 和 美元符 “$”
- 数字不能开头
- 其中不能包含空格
- 不能使用关键字和保留字,但是可以包含关键字和保留字
- Java严格区分大小写,但是长度无限制。
命名的规范
- 包名: 所有字母都小写。 如: abcd
- 类名、接口名:若出现多个单词,每个单词首字母都大写。如: AaaBbbCcc
- 方法名、变量名: 若出现多个单词,第一个单词的首字母小写,其余单词首字母都大写。如: aaaBbbCcc
- 常量名: 所有字母都大写,每个单词之间以 “_” 分隔。 如: AAA_BBB_CCC
变量
- 变量的格式: 数据类型 变量名 = 值;
//声明一个变量
数据类型 变量名; 如: int num;//为变量赋值
变量名 = 值; 如: num = 10;//声明一个变量并赋值
int num = 10; - 变量的概念:
①在内存中开辟一块内存空间
②该空间有名称(变量名)有类型(数据类型)
③变量可以在指定的范围内不断的变化 - 变量的注意:
①作用域:从变量定义的位置开始,到该变量所在的那对大括号结束
②局部变量在使用前必须赋初始值
③先声明,后使用
数据类型
- 基本数据类型
类型 字节数 二进制位数
byte (字节型) 1 8
short(短整型) char (字符型) 2 16
int (整型) float (单精度浮点数) 4 32
long (长整型) double (双精度浮点数) 8 64
布尔型:boolean true false
2.引用数据类型
|—类(class) —————- String 字符串
|—接口(interface)
|—数组([ ])
基本数据类型之间的转换
- 自动类型转换:范围小→范围大
byte→short→int→long→float→double;
char→int→long→float→double - 强制类型转换:范围大→范围小
需要加强制转换符
转义字符
\n 换行 \r 回车 \t 水平制表 ‘ 单引号 ” 双引号 \斜杠
运算符
算术运算符:+ 、 – 、 * 、 / 、 % 、 ++ 、 —
赋值运算符:= 、 += 、 -= 、 *= 、 /= 、 %=
关系运算符:> 、 < 、 >= 、 <= 、 == 、 !=
逻辑运算符:! 、 & (只要有一个false 最终结果就是false)
| (但凡有一个true 最终结果就是true)
^ (如果两边一样 最终结果为false 如果两边不同 最终结果为true)
&&(如果第一个是false 那第二个不执行 最终结果是false)
||(如果第一个表达式的结果是true 那第二个表达式 就不去计算了 ,最终结果是true)
位运算符: ~ 、 >> 、 << 、 >>>
字符串连接运算符:+
三目运算符:X ? Y :Z
X为boolean类型表达式,先计算x的值,若为true,整个三目运算的结果为表达式Y的值,否则整个运算结果为表达式Z的值
程序流程控制
结构化程序的三种结构:
顺序、选择(分支)、循环
条件判断:
if(条件表达式){
//当条件表达式结果为 true 时,需要执行的语句
}
if(条件表达式){
//当条件表达式结果为 true 时,需要执行的语句
}else{
//当条件表达式结果为 false 时,需要执行的语句
}
if(条件表达式1){
//当条件表达式1 结果为 true 时,需要执行的语句
}else if(条件表达式2){
//当条件表达式2 结果为 true 时,需要执行的语句
}else if(条件表达式3){
//当条件表达式3 结果为 true 时,需要执行的语句
}
……
else{
//当上述条件表达式结果都为 false 时,需要执行的语句
}
注意:
①当某个条件表达式结果为true, 执行相应的语句,其他 else if 将不再执行
②if-else 语句可以嵌套的
选择结构:
switch(表达式){
case 值1 :
//执行的语句
break;
case 值2 :
//执行的语句
//break;
case 值3 :
//执行的语句
break;
……
default :
//执行的语句
break;
}
//需求:若一个数大于2 小于5 打印 “2-5”
int i = 2;
switch(i){
case 1:
System.out.println("一");
break;
case 2:
case 3:
case 4:
case 5:
System.out.println("2-5");
break;
}
注意:
1、表达式必须是int、byte、char、short、enmu、String类型
2、constN必须是常量或者finall变量,不能是范围
3、所有的case语句的值不能相同,否则编译会报错
4、default可要可不要
5、break用来执行完一个分支后使程序跳出switch语句块,否则会一直会执行下去。
循环结构:
for ([循环变量初始值设定]; [循环条件判断]; [改变循环变量的值]){
循环体
}
注意:
1、表达式2一般不可以省略,否则死循环
2、表达式3可以省略,但是在循环体中必须有语句修改变量,以使表达式2在某一时刻为false结束循环。
3、若同时省略表达式1,表表达式3,则相当于while(表达式2)语句
4、三个表达式均省略 即for(;;)语句,此时相当于while(true)语句
5、表达式1、表达式3可以是逗号表达式,以使循环变量值在修改时可以对其它变量赋值
while( 条件表达式语句){
循环体语句;
}
[初始条件]
do{
循环体;
[迭代]
}while( 循环条件判断);
注意:
1、当第一次执行时,若表达式=false时,则while语句不执行,而do/while语句执行一次后面的语句
2、一定要切记在switch循环中,如果没有break跳出语句,每一个case都要执行一遍,在计算最终结果。
嵌套循环: 一个循环充当了另一个循环的循环体
打印100以内的质数:
boolean flag = true;
for(int i = 2; i <= 100; i++){
for(int j = 2; j < i; j++){
if(i % j == 0){
flag = false;
break;
}
}
if(flag){
System.out.println(i);
}
flag = true;
}
特殊流程控制语句:结束多层for循环
label:for(int i = 0; i < 100; i++){
for(int j = 0; j < 100; j++){
if(j == 13){
System.out.println(j);
break label;
}
}
}
break和continue区别:
break: 结束“当前”循环 。当用于switch-case语句时,用于结束当前 switch-case 语句
continue: 结束“当次”循环
注意:if外有循环可以用break、continue,单纯if不可以用。
if和switch的区别:
if可以判断范围,也可以判断一个值
switch只能判断指定的值
若只判断指定的值,则使用switch语句,效率快
if判断范围,对数据判断灵活,自身的格式也比较灵活
while 和 do-while 的区别?
while : 先判断循环条件,再执行循环体
do-while : 先执行循环体,再判断循环条件。(至少执行一次)
方法的声明和使用
方法:也叫函数,是一个功能的定义。是一个类中最基本的功能单元
//需求: 计算一个数 * 2 + 1 的结果
int a = 10;
System.out.println(a * 2 + 1);
a = 5;
System.out.println(a * 2 + 1);
a = 8;
System.out.println(a * 2 + 1);
1.为什么使用方法?
减少重复代码,提供代码复用性
使用方法将功能提炼出来
写在类内
2.声明格式
[修饰符] 返回值类型 方法名([形式参数列表]){
程序代码;
[return 返回值;]
}
注意:
1、“返回值类型”与 “返回值”的数据类型需要保持一致
2、调用方法通过方法名和参数列表,注意方法名和参数列表(参数的个数、参数的类型)必须一致
3、若声明了“返回值类型”说明该方法运行后有结果,若调用者需要用到该结果可以声明同类型变量接收。
4、方法中只能调用方法,不能声明其他方法
5、若方法运行结束后,不需要返回任何结果给调用者时,方法“返回值类型”处声明为 void
void : 表示没有返回值
3. 声明方法的两点明确
1、方法是否需要返回结果给调用者
明确是否需要返回值类型,返回值类型是什么
2、方法是否有未知的数据参与运算
明确是否需要参数列表,需要几个
跨类调用方法:
通过“类名.方法名" 方式调用。 (暂时使用static修饰的方法为例)
return
1. 将数据返回给调用者,除了void外,return后必须跟着返回值,只能返回一个。
2. 终止方法的执行,返回数据类型必须是void,return后不能添加数据。
3. 当return结束方法的时候,要让其后面的代码有可能被执行到。
4. 一个方法里可以有多个return,在void里不能有返回值,其他的必须有返回值。
重载overload
1、在一个类中,方法名字相同,参数类型不同。
参数类型不同:个数、数据类型、顺序。
注意:
1、重载和返回值类型,修饰符没有任何关系。
2、参数变量名修改也不能够重载
public void show(char c, int a){}
public void show(int a, char c){}
public void show(int a, char c, double d){}
public void show(String str, int a){}
public void shows(char c, int a){}
递归
-
有返回值
-
有参数
-
能够有跳出循环的控制语句
- 自己调用自己
面向对象编程
特点:
将复杂的事情简单化。
面向对象将以前的过程中的执行者,变成了指挥者。
面向对象这种思想是符合现在人们思考习惯的一种思想。
面向对象和面向过程
1. 面向对象:是以具体的事物为单位,考虑的是它的特征(属性)和行为(方法)。
2. 面向过程:是以具体的流程为单位,考虑功能的实现。
(理解)把大象装冰箱一共分几步?
①打开冰箱 ②把大象装进去(存储大象) ③关闭冰箱
如何使用面向对象思想思考上述问题呢?
人{
拉(冰箱){
冰箱.打开()
}
指挥(动物){
动物.进入()
}
推(冰箱){
冰箱.关闭()
}
}
冰箱{
打开(){}
存储(){}
关闭(){}
}
大象{
进入(){}
}
猴{
进入(){}
}
面向对象更加注重前期的设计
1.就是对类的设计
2.设计类就是设计类的成员:属性 & 方法
面向对象:将现实生活中一类事物的共性内容进行提取,抽象成相应Java类,用Java中类对其进行描述
现实生活中的事物: 小猫 小狗 大象
共性内容: 名称 性别 年龄 吃饭的功能 睡觉的功能
class Animal{
//属性
String name;
char gender;
int age;
//方法-行为
public void eat(){
System.out.println("吃饭");
}
public void sleep(){
System.out.println("睡觉");
}
}
若需要具体到某一个事物,通过 new 关键字创建对象
Animal a1 = new Animal(); //
a1.name = "大象";
a1.gender = '男';
a1.age = 2;
a1.eat();
a1.sleep();
System.out.println(a1.name + "," + a1.age);
类和对象
1、对象:是一个实实在在的个体
类:对现实生活中一类事物的描述,抽象的
2、类和对象的关系:
类是对象的模板/抽象化的概念,对象是类的实例。
3、创建类和对象
类:
特征:全局变量/属性/成员变量
动作:方法
对象:
类名 对象名=new 类名()
注意:一个类可以创建多个对象,,每个对象之间没有关系。
成员变量和局部变量的区别:
1:成员变量直接定义在类中。
局部变量定义在方法中,参数上,语句中。
2:成员变量在这个类中有效。
局部变量只在自己所属的大括号内有效,大括号结束,局部变量失去作用域。
3:成员变量存在于堆内存中,随着对象的产生而存在,消失而消失。
局部变量存在于栈内存中,随着所属区域的运行而存在,结束而释放。
内存管理:
分配: JVM自动为其分配内存空间
释放:JVM通过垃圾回收机制自动的释放内存空间
垃圾回收机制: 将内存中的垃圾对象释放
垃圾对象:不再被任何引用指向的对象
Person p = new Person();
p = null;
System.gc(); //通知垃圾回收机制可以释放内存,但是并不能保证立即释放,加快释放。
构造函数:
属性
方法
构造器
1. 构造器的格式
访问控制修饰符 类名(参数列表){
//初始化语句
}
2. 构造器的作用
①创建对象
②为对象进行初始化
3. 构造器的注意:
①构造器的名称必须与类名一致!
②若一个类中没有显示提供任何构造器,系统会自动提供一个默认无参构造器
public Person(){}
③若一个类中显示的提供了任何构造器,系统默认构造器将不再提供
④构造器只能调用一次,并且是在创建对象时调用
4. 构造器的重载
①构造器的名称必须相同
②构造器的参数列表必须不同(参数的个数、参数的类型)
5. 为属性赋初始值的方式
①使用默认赋值
②直接显示赋值
③构造器
顺序:①②③
class Person{
private String name;
private int age;
private char gender;
public Person(){
cry();
}
public Person(String name){
this.name = name;
}
public Person(String name, int age){
this(name);
this.age = age;
}
public Person(String name, int age, char gender){
this(name, age);
this.gender = gender;
}
public void setName(String name){
this.name = name;//可以区分局部变量和成员变量
}
public void cry(){
System.out.println("哭");
}
}
Person p = new Person("张三");
//p.cry();
Person p1 = new Person();
//p1.cry();
“Person p = new Person();”
创建一个对象都在内存中做了什么事情?
1:先将硬盘上指定位置的Person.class文件加载进内存。
2:执行main方法时,在栈内存中开辟了main方法的空间(压栈-进栈),然后在main方法的栈区分配了一个变量p。
3:在堆内存中开辟一个实体空间,分配了一个内存首地址值。new
4:在该实体空间中进行属性的空间分配,并进行了默认初始化。
5:对空间中的属性进行显示初始化。
6:进行实体的构造代码块初始化。
7:调用该实体对应的构造函数,进行构造函数初始化。()
8:将首地址赋值给p ,p变量就引用了该实体。(指向了该对象)
This
代表对象,就是所在函数所属对象的引用。
this到底代表什么呢?哪个对象调用了this所在的函数,this就代表哪个对象,就是哪个对象的引用。
开发时,什么时候使用this呢?
在定义功能时,如果该功能内部使用到了调用该功能的对象,这时就用this来表示这个对象。
this 还可以用于构造函数间的调用。
调用格式:this(实际参数);
this对象后面跟上 . 调用的是成员属性和成员方法(一般方法);
this对象后面跟上 () 调用的是本类中的对应参数的构造函数。
注意:用this调用构造函数,必须定义在构造函数的第一行。因为构造函数是用于初始化的,所以初始化动作一定要执行。否则编译失败。
static
关键字,是一个修饰符,用于修饰成员(成员变量和成员函数)。
特点:
1、static变量
按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量;另一种是没有被static修饰的变量,叫实例变量。两者的区别是:
对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。
对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。
2、静态方法
静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,
不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法)只能访问所属类的静态成员变量和成员方法。
因为实例成员与特定的对象关联!这个需要去理解,想明白其中的道理,不是记忆!!!
因为static方法独立于任何实例,因此static方法必须被实现,而不能是抽象的abstract。
3、static代码块
static代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。
4、static和final一块用表示什么
static final用来修饰成员变量和成员方法,可简单理解为"全局常量"!
对于变量,表示一旦给值就不可修改,并且通过类名可以访问。
对于方法,表示不可覆盖,并且可以通过类名直接访问。
备注:
1,有些数据是对象特有的数据,是不可以被静态修饰的。因为那样的话,特有数据会变成对象的共享数据。这样对事物的描述就出了问题。所以,在定义静态时,必须要明确,这个数据是否是被对象所共享的。
2,静态方法只能访问静态成员,不可以访问非静态成员。
(这句话是针对同一个类环境下的,比如说,一个类有多个成员(属性,方法,字段),静态方法A,那么可以访问同类名下其他静态成员,你如果访问非静态成员就不行)
因为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。
3,静态方法中不能使用this,super关键字。
因为this代表对象,而静态在时,有可能没有对象,所以this无法使用。
4,主函数是静态的。
成员变量和静态变量的区别:
1,成员变量所属于对象。所以也称为实例变量。
静态变量所属于类。所以也称为类变量。
2,成员变量存在于堆内存中。
静态变量存在于方法区中。
3,成员变量随着对象创建而存在。随着对象被回收而消失。
静态变量随着类的加载而存在。随着类的消失而消失。
4,成员变量只能被对象所调用 。
静态变量可以被对象调用,也可以被类名调用。
所以,成员变量可以称为对象的特有数据,静态变量称为对象的共享数据。
静态代码块:就是一个有静态关键字标示的一个代码块区域。定义在类中。
作用:可以完成类的初始化。静态代码块随着类的加载而执行,而且只执行一次(new 多个对象就只执行一次)。如果和主函数在同一类中,优先于主函数执行。
final
根据程序上下文环境,Java关键字final有"这是无法改变的"或者"终态的"含义,它可以修饰非抽象类、非抽象类成员方法和变量。
你可能出于两种理解而需要阻止改变、设计或效率。
final类不能被继承,没有子类,final类中的方法默认是final的。
final方法不能被子类的方法覆盖,但可以被继承。
final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
final不能用于修饰构造方法。
注意:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。
1、final类
final类不能被继承,因此final类的成员方法没有机会被覆盖,默认都是final的。
在设计类时候,如果这个类不需要有子类,类的实现细节不允许改变,并且确信这个类不会载被扩展,那么就设计为final类。
2、final方法
如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。
使用final方法的原因有二:
第一、把方法锁定,防止任何继承类修改它的意义和实现。
第二、高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。
3、final变量(常量)
用final修饰的成员变量表示常量,值一旦给定就无法改变!
final修饰的变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。
从下面的例子中可以看出,一旦给final变量初值后,值就不能再改变了。
另外,final变量定义的时候,可以先声明,而不给初值,这中变量也称为final空白,无论什么情况,编译器都确保空白final在使用之前必须被初始化。但是,final空白在final关键字final的使用上提供了更大的灵活性,为此,一个类中的final数据成员就可以实现依对象而有所不同,却有保持其恒定不变的特征。
4、final参数
当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。
生成Java帮助文档:命令格式:javadoc –d 文件夹名 –auther –version *.java
/** //格式
*类描述
*@author 作者名
*@version 版本号
*/
/**
*方法描述
*@param 参数描述
*@return 返回值描述
*/
super
(1)使用super关键字, super代表父类对象super代表父类对象,只能用在子类中
(2)可在子类构造方法中调用且必须是该方法中第一句
(3)不能使用在static修饰的方法中
(4)super的用处
访问父类构造方法
super();
super(name);
访问父类属性
super.name;
访问父类方法
super.print();
抽象类: abstract
抽象:不具体,看不明白。抽象类表象体现。
在不断抽取过程中,将共性内容中的方法声明抽取,但是方法不一样,没有抽取,这时抽取到的方法,
并不具体,需要被指定关键字abstract所标示,声明为抽象方法。
抽象方法所在类一定要标示为抽象类,也就是说该类需要被abstract关键字所修饰。
抽象类的特点:
1:抽象方法只能定义在抽象类中,抽象类和抽象方法必须由abstract关键字修饰(可以描述类和方法,不可以描述变量)。
2:抽象方法只定义方法声明,并不定义方法实现。
3:抽象类不可以被创建对象(实例化)。
4:只有通过子类继承抽象类并覆盖了抽象类中的所有抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。
抽象类的细节:
1:抽象类中是否有构造函数?有,用于给子类对象进行初始化。
2:抽象类中是否可以定义非抽象方法?
可以。其实,抽象类和一般类没有太大的区别,都是在描述事物,只不过抽象类在描述事物时,有些功能不具体。
所以抽象类和一般类在定义上,都是需要定义属性和行为的。
只不过,比一般类多了一个抽象函数。而且比一般类少了一个创建对象的部分。
3:抽象关键字abstract和哪些不可以共存?final , private , static
4:抽象类中可不可以不定义抽象方法?可以。抽象方法目的仅仅为了不让该类创建对象。
面向对象的特征(封装)
封装是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处:将变化隔离;便于使用;提高重用性;安全性
封装原则:将不需要对外提供的内容都隐藏起来,把属性都隐藏,提供公共方法对其访问。
面向对象的特征(继承)
好处:
1:提高了代码的复用性。
2:让类与类之间产生了关系,提供了另一个特征多态的前提。
父类的由来:其实是由多个类不断向上抽取共性内容而来的。
java中对于继承,java只支持单继承。java虽然不直接支持多继承,但是保留了这种多继承机制,进行改良。
单继承:一个类只能有一个父类。
多继承:一个类可以有多个父类。
为什么不支持多继承呢?
因为当一个类同时继承两个父类时,两个父类中有相同的功能,那么子类对象调用该功能时,运行哪一个呢?因为父类中的方法中存在方法体。
但是java支持多重继承。A继承B B继承C C继承D。
多重继承的出现,就有了继承体系。体系中的顶层父类是通过不断向上抽取而来的。它里面定义的该体系最基本最共性内容的功能。
所以,一个体系要想被使用,直接查阅该系统中的父类的功能即可知道该体系的基本用法。、
那么想要使用一个体系时,需要建立对象。建议建立最子类对象,因为最子类不仅可以使用父类中的功能。
还可以使用子类特有的一些功能。
简单说:对于一个继承体系的使用,查阅顶层父类中的内容,创建最底层子类的对象。
子父类出现后,类中的成员都有了哪些特点:
1:成员变量。
当子父类中出现一样的属性时,子类类型的对象,调用该属性,值是子类的属性值。
如果想要调用父类中的属性值,需要使用一个关键字:super
This:代表是本类类型的对象引用。
Super :代表是子类所属的父类中的内存空间引用。
注意:子父类中通常是不会出现同名成员变量的,因为父类中只要定义了,子类就不用在定义了,直接继承过来用就可以了。
2:成员函数。
当子父类中出现了一模一样的方法时,建立子类对象会运行子类中的方法。
好像父类中的方法被覆盖掉一样。所以这种情况,是函数的另一个特性:覆盖(复写,重写)
什么时候使用覆盖呢?当一个类的功能内容需要修改时,可以通过覆盖来实现。
3:构造函数。
发现子类构造函数运行时,先运行了父类的构造函数。为什么呢?
原因:子类的所有构造函数中的第一行,其实都有一条隐身的语句super();
super(): 表示父类的构造函数,并会调用于参数相对应的父类中的构造函数。而super():是在调用父类中空参数的构造函数。
为什么子类对象初始化时,都需要调用父类中的函数?(为什么要在子类构造函数的第一行加入这个super()?)
因为子类继承父类,会继承到父类中的数据,所以必须要看父类是如何对自己的数据进行初始化的。
所以子类在进行对象初始化时,先调用父类的构造函数,这就是子类的实例化过程。
注意:子类中所有的构造函数都会默认访问父类中的空参数的构造函数,因为每一个子类构造内第一行都有默认的语句super();
如果父类中没有空参数的构造函数,那么子类的构造函数内,必须通过super语句指定要访问的父类中的构造函数。
如果子类构造函数中用this来指定调用子类自己的构造函数,那么被调用的构造函数也一样会访问父类中的构造函数。
问题:super()和this()是否可以同时出现的构造函数中。
两个语句只能有一个定义在第一行,所以只能出现其中一个。
super()或者this():为什么一定要定义在第一行?
因为super()或者this()都是调用构造函数,构造函数用于初始化,所以初始化的动作要先完成。
继承的细节:
什么时候使用继承呢?
当类与类之间存在着所属关系时,才具备了继承的前提。a是b中的一种。a继承b。狼是犬科中的一种。
英文书中,所属关系:” is a “
注意:不要仅仅为了获取其他类中的已有成员进行继承。
所以判断所属关系,可以简单看,如果继承后,被继承的类中的功能,都可以被该子类所具备,那么继承成立。如果不是,不可以继承。
细节二:
在方法覆盖时,注意两点:
1:子类覆盖父类时,必须要保证,子类方法的权限必须大于等于父类方法权限可以实现继承。否则,编译失败。
2:覆盖时,要么都静态,要么都不静态。 (静态只能覆盖静态,或者被静态覆盖)
继承的一个弊端:打破了封装性。对于一些类,或者类中功能,是需要被继承,或者复写的。
这时如何解决问题呢?介绍一个关键字,final:最终。
final特点:
1:这个关键字是一个修饰符,可以修饰类,方法,变量。
2:被final修饰的类是一个最终类,不可以被继承。
3:被final修饰的方法是一个最终方法,不可以被覆盖。
4:被final修饰的变量是一个常量,只能赋值一次。
其实这样的原因的就是给一些固定的数据起个阅读性较强的名称。
不加final修饰不是也可以使用吗?那么这个值是一个变量,是可以更改的。
加了final,程序更为严谨。常量名称定义时,有规范,所有字母都大写,如果由多个单词组成,中间用 _ 连接。
面向对象的特征(多态)
1. 多态的体现: ①方法的重载与重写 ②对象的多态性
2.对象的多态性:父类的引用指向子类的对象
Person p = new Man(); // 多态-向上转型
p.eat();
p.walk(); //虚拟方法调用
//p.smoking();
Man man = (Man)p; //向下转型
man.smoking();
Java程序的运行分为两种状态:
在多态的情况下,编译时, “看左边”,看的是父类的引用(父类中不具备子类特有的方法)
运行时,“看右边”,看的是子类对象,实际运行的是子类重写父类的方法
———— 以上过程被称为“虚拟方法调用(动态绑定)”
3. 多态的前提:①要有继承关系 ②方法的重写(完成虚拟方法调用)
4. 引用数据类型之间的转换:
前提:要有继承关系
向上转型: 子类转父类。系统自动完成转换
向下转型: 父类转子类。需要使用强转符 “(需要转换的类型)”
可能引发 java.lang.ClassCastException
Person p = new Man();
Woman woman = (Woman)p; //编译? YES 运行? NO
5. Java 为了解决上述问题,提供了相应的解决办法
instanceof 运算符:
如:
p instanceof Man : 判断 p 引用指向的对象是不是 Man 的本类类型及 Man 的子类类型,如果是返回 true
Person p = new Man();
if(p instanceof Woman){
Woman woman = (Woman)p;
}
多态的应用:
多态的应用之一:多态数组
Person[] persons = new Person[3];//该多态数组中可以存放Person本类类型的对象及Person子类类型的对象
persons[0] = new Person();
persons[1] = new Man();
persons[2] = new Woman();
for(int i = 0; i < persons.length; i++){
persons[i].eat();//虚拟方法调用
}
多态的应用之二: 多态参数
//需求:展示一个男人吃饭和走路的功能
/*public void show(Man man){
man.eat();
man.walk()
}
public void show(Woman woman){
woman.eat();
woman.walk();
}*/
public void show(Person p){ //多态参数:当调用方法时,可以传递Person本类类型的对象及Person子类类型的对象
p.eat();
p.walk();//虚拟方法调用
if(p instanceof Man){
Man man = (Man)p;
man.smoking();
}
}
equals和==的区别?
object中的equals比较的是地址,底层封装的是==
==比较的是基本数据类型,比较的是内容
引用数据类型比较的是地址
String中也有equals,String中的equals被重写过了,比较的是内容。
内部类
分类:成员内部类、静态内部类、局部内部类、匿名内部类
1、成员内部类:
1、可以用四种访问权限修饰符修饰
2、可以有自己的属性和方法,除了静态的。
3、可以使用外部类的所有属性和方法,包括私有的。
4、创建对象
1、通过创建外部类对象的方式创建对象
外部类 外部类对象=new 外部类();
内部类 对象名=外部类对象.new 内部类();
2、内部类 对象名=new 外部类.new 内部类();
2、静态内部类
1、格式:static class 类名{}
2、可以声明静态的属性和方法
3、可以使用外部的静态的属性和方法
4、创建对象
内类名 对象名=new 内类名();(可以直接创建)
外部类名.内部类 对象名=new 外部类.内部类();
包名.外部类名.内部类 对象名=new 包名.外部类.内部类();
5、外部类与内部类同名时,默认是使用内部类对象调用外部类属性
this代表内部类对象
6、要想使用外部类属性,需要使用外部类对象调用
3、局部内部类
1、在方法中声明
2、只能用default修饰
3、可以声明属性和方法,但不能是静态的
4、创建对象,必须在声明内部类的方法内创建
5、调用方法的时候,局部内部类才会被执行
4、匿名内部类
1、匿名内部类只是用一次
2、格式:
父类或接口名 对象名=new 父类或接口名(参数列表){
重写抽象方法
}
调用抽象方法:对象名.方法名
数组及常用算法
一维数组
1、声明:
int a[]; int []b;
2、初始化:
动态初始化:1、a=new int[2]; int[0]=1;...
动态初始化:2、b=new b[]{3,4};
静态初始化:int [] c={5,6};
3、数组常用的方法:
排序:Array.sort();
查找:Array.binarySearch();
打印:Array.toString();
复制:Array.copyof();
4、常用操作
1、冒泡排序
for(int i=0;i<a.length-1;i++){//控制外循环的次数
for(int j=0;j<a.length-1-i;j++){//控制内循环次数,比外循环少一次,与下一个比较
if(a[j]>a[j+1]){
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
2、选择排序
for (int i = 0; i < a.length-1; i++) {
int k=i;
for (int j = i; j < a.length-1; j++) {
if (a[k]>a[j+1]) {
k=j+1;
}
}
if(i!=k){
int temp=a[i];
a[i]=a[k];
a[k]=temp;
}
}
3、顺序查找
public static int find(int []b,int a){
for (int i = 0; i < b.length; i++) {
if (a==b[i]) {
return i;
}
}
return -1;
}
4、二分查找
public static int find(int b[],int a){
int max=b.length-1;
int min=0;
for (int i = 0; i < b.length; i++) {
int midle=(max+min)/2;
if(a==b[midle]){
return midle;
}else if(a>b[midle]){
min=midle+1;
}else if(a<b[midle]){
max=midle-1;
}
}
return -1;
}
结尾
java总结上部分差不多就结束了,由于有些知识超纲后续发现不足会进行修改,望各位大牛多多指点
暂无评论内容