一、形参问题_匿名对象_static关键字
1.形式参数问题
一个方法的形式参数是基本数据类型:形式参数的改变不会影响实际参数!(需要什么类型,传递具体数据类型的对应数据值即可!)
一个方法的形式参数是引用数据类型:除过String类型,形式参数的改变会直接影响实际参数!
如果一个方法的形式参数是一个引用类型:类
调用方法的时候,实际参数是当前这个类的对象!(空间地址值)
2.匿名对象
匿名对象:没有名字的对象!
格式:
new 类名();
匿名对象的特点:
1)直接在堆内存中开辟空间,使用完毕,被垃圾回收器回收(用完就回收了)
2)匿名对象在实际开发中使用较多;匿名对象不要多次使用,使用一次即可!
3)匿名对象可以作为参数传递!
3.static关键字
static:共享、共用的意思
特点:
1)被static修饰的成员(变量)方法随着类的加载而加载,优先于对象存在!
(对象创建方式: 类名 对象名 = new 类名();)
某个类要先被编译产生--->类名.class--->类在运行的时候,加载过程要将静态的成员都先进入方法区的静态区中!
2)static和this不能共存
this:代表当前类对象的地址值引用---说明对象创建完毕,才能使用。
this.变量名--->访问成员变量(对象成员)
3)如果有一个变量体现出被共享,被共用---->此时用“static”修饰。
4)访问方式:(必须记住)
类成员--->被static修饰的,特有访问方式
类名.变量名(); 在访问本类中的静态变量
类名.方法名(); 在访问本类中的静态方法
注意:
我们所说的成员变量/成员方法---->默认 非静态的!
静态static的使用注意事项:
1)非静态的成员方法里面,皆可以访问静态的变量/方法,也可以访问非静态的变量/方法
2)静态的方法只能访问静态的成员,不能访问非静态的!
记住:静态只能访问静态!
使用static---自定义数组工具类--->提供相关功能
需求:
* 已知一个数组,静态初始化,给数组中加入遍历功能,进行测试!
* 从最早开始定义方法--->面向对象的访问方式的过程!
* 自定义一个类工具类,构造方法私有化,对外提供静态的功能,对这个工具类产生 "文档说明书"
* 找到ArrayTool.java文件所在的目录
* 在dos窗口中输入指令
* javadoc -d 目录名称 -author -version java源文件名称 (前提条件是这个ArrayTool类必须是public修饰)
*
* 举例:
* javadoc -d doc -author -version ArrayTool.java
packagecom.qianfeng.day12;
publicclassArrayTool{
/**
*ArrayTool这个类是自定义针对数组操作的工具类
*里面提供了数组遍历,求数组最值,查询指定元素第一次索引值,逆序,冒泡排序等等这些功能
*@author小白菜
*@versionV1.8
**/
//提供无参构造方法,无参构造私有化---目的就是为了让外界类不能创建对象!
privateArrayTool(){}
/**
*这功能是对数组进行遍历的功能,
*最终数组以[元素1,元素2,元素3,...元素n]形式出现
*@paramarray传递的数组
*
**/
publicstaticvoidprintArray(int[]array){
System.out.print("[");
//遍历数组
for(inti=0;i<array.length;i++){
if(i==array.length-1){
System.out.println(array[i]+"]");
}else{
System.out.print(array[i]+",");
}
}
}
/**
*该方法是针对数组的求最大值的功能
*@paramarray指定数组
*@return返回值是表示数组中出现的最大值
**/
publicstaticintgetArrayMax(int[]array){
//定义中参照物
intmax=array[0];
for(intx=1;x<array.length;x++){
if(array[x]>max){
max=array[x];
}
}
returnmax;
}
/**
*该功能是查询数组中的元素第一次出现索引值
*@paramarray需要在指定数组中查询
*@paramkey要查询指定的数组中的元素
*@return在数组中寻找对应元素的索引值,找到返回对应索引值,没有返回-1
**/
publicstaticintgetIndex(int[]array,intkey){
//假设
intindex=-1;
//遍历数组
for(intx=0;x<array.length;x++){
if(key==array[x]){
index=x;
break;
}
}
returnindex;
}
/***
*该功能是针对数组进行冒泡排序,两两比较,将较大的值往后放,
*第一次比较完毕,最大值出现在最大索引处!
*@paramarray要输入指定数组进行冒泡排序
*/
publicstaticvoidbubleSort(int[]array){
for(intx=0;x<array.length-1;x++){
for(inty=0;y<array.length-1-x;y++){
if(array[y]>array[y+1]){
inttemp=array[y];
array[y]=array[y+1];
array[y+1]=temp;
}
}
}
}
/***
*该功能是将数组逆序,将第一个元素和最后一个元素进行互换,第二个元素和倒数第二个元素互换
*依次这样操作,将数组逆序
*@paramarray传入指定数组进行逆序
*/
publicstaticvoidreverseArray(int[]array){
for(intstart=0,end=array.length-1;start<end;start++,end--){
inttemp=array[start];//array[0]
array[start]=array[end];//array[array.lengtt-1]
array[end]=temp;
}
}
}
测试类
//测试类
public class ArrayTest {
public static void main(String[] args) {
//已知一个数组,静态初始化
int[] arr = {54,87,29,32,13} ;
//调用ArrayTool类的所有静态功能
int max = ArrayTool.getArrayMax(arr);
System.out.println("最大值是:"+max);
System.out.println("------------------------------");
ArrayTool.bubleSort(arr) ;
//遍历
ArrayTool.printArray(arr );
System.out.println("-------------------------------");
ArrayTool.reverseArray(arr);
//遍历
ArrayTool.printArray(arr);
System.out.println("--------------------------------");
//逆序值,查询13这个元素第一次出现的角标
int index = ArrayTool.getIndex(arr, 13);
System.out.println(index);
int index2 = ArrayTool.getIndex(arr,300) ;
System.out.println(index2);
}
}
4.代码块
代码块:Java中的代码块是{}包裹起来的内容
分类:
局部代码块---->方法中
作用:限定局部变量的生命周期
构造代码块--->类的成员位置定义的{}
作用:在执行构造方法之前,如果存在构造代码快,先执行构造代码快,然后执行构造方法,就是给数据进行初始化!
静态代码块--->类的成员位置定义
static{}
特点:跟类相关,类一加载先执行,而且只执行一次(因为类就加载一次)优先级最大。
优先级:静态代码块>构造代码块>构造方法
二、继承
1.继承的概念
将多个类的共性内容抽取到一个独立类中,这个独立的类和多个类产生一种关系“继承!”
2.继承的格式
class 父类名{}
class 子类名 extends 父类名{}
3.继承的好处
1)可以提高代码复用性;
2)可以增强代码后期维护;
3)类与类的关系:继承 是多态的前提条件
使用“继承”的时机:
不能为了使用部分功能就使用继承!
使用继承的前提条件:
如果一个类A是类B的一种,或者类B是类A的一种,才能使用继承,继承的核心思想体现出一种“is a”的关系
实际开发中:低耦合 高内聚
所有的开发原则都遵循“低耦合 高内聚”
耦合:类和类的关系越少越好,耦合性只能降低,不能避免!
内聚:解决某件事情(功能)的执行力!(一个类能完成的尽量一个类完成,不能产生过多关系!)
4.继承的特点
1)在java语言中,类与类的关系只支持单继承(类是java中最基本的单元)
2)类与类之间虽然不支持多继承,但是可以多层继承!
5.继承的注意事项:
1)子类继承父类,是可以继承父类的所有东西,只不过父类的私有属性以及方法只能在本类中访问,类是不能直接访问到的,但是可以间接的通过公共方法来访问!
2)子类继承父类,不能继承父类的构造方法(无参/有参构造),可以通过“super”来访问父类的构造方法
6.继承关系中成员问题
1)子类继承父类,子类中成员变量如果与父类中的成员变量不一致的情况:
比较简单,分别访问即可!
2)子类继承父类,如果子类中成员变量名称与父类中成员变量名称一致:
a)先在子类的局部位置(子类的成员方法中定义变量:局部变量)找,如果存在,就使用
b)如果子类的局部位置没有,然后才在子类的成员位置找,如果存在,就使用
c)如果子类的成员位置没有,然后在父类的成员位置找,如果存在,就使用
d)如果父类的成员位置也没有,说明当前没有这个变量,就访问报错!
一句话:就近原则!
7.继承关系中子类继承父类,子类如何访问父类的构造方法
通过super关键字
1)子类继承父类,不能继承父类的构造方法,但是可以通过super访问,子类的所有构造方法默认访问父类的无参构造方法!
原因:子类继承父类,可能用到父类的属性(成员变量)这些数据,必须让父类先初始化,然后子类才能初始化(构造方法,就是给数据初始化的)
这种过程--->继承中“分层初始化”
2)永远建议把父类的无参构造方法给出来,否则可能会导致子类的构造方法报错!
8.继承关系中,成员方法的访问:
子类继承父类,如果子类和父类的方法名不一致,分别调用即可!
如果子类出现和父类一模一样的方法,子类将父类的功能进行覆盖(复写/重写)
---override:方法重写
9.变量---->成员变量/局部变量
将一个变量定义为成员变量的时机:
如果这个变量能够描述现实世界事物的属性--->定义为成员变量,否则都是局部变量
10.方法重写和方法重载的区别
override和overload的区别
11.方法重载与方法重写的区别
方法重写
在定义方法的时候,为了提高功能的扩展性,同一个方法名可以使用不同的参数进行传递!
方法名相同,参数列表不同,与返回值无关!
参数列表不同:
1)参数个数
2)参数类型
3)类型的先后顺序
方法重写:
是在继承关系中使用
子类继承父类,子类的功能想沿用父类的功能,同时使用自己的功能,子类出现了和父类一模一样的方法----方法重写(覆盖/复写)
12.this和super的区别
概念区别
this:代表是当前类对象的地址值引用
super:代表父类的对象的地址值引用(父类的空间标识)
成员访问的区别:
this.变量名; 访问本类的成员变量
super.变量名 访问父类的成员变量
this.方法名(); 访问本类的成员方法
super.方法名(); 访问父类的成员方法
this(); 访问本类的无参构造
this(xxx); 访问本类的有参构造
super(); 访问父类的无参构造
super(xxx); 访问父类的有参构造
13.final关键字
final:是一个状态修饰符 基本概念:(最终的,无法更改的)
特点:
1)修饰类,该类不能被继承!(当前这个类是最终类,无法来提供派生类(子类))
2)修饰成员方法,该成员方法不能重写(保证父类的安全性!)
3)修饰变量,此时该变量是一个常量,不能在重新赋值!
常量:
编译时期常量---->基本数据类型:四类八种 (jvm不需要加载)
public static final int a = 10 ;
运行时期常量---->引用数据类型: (jvm进行加载,引用类型 除过String)
int类型--->包装类 类型 Integer类
public static final Integer i = new Integer(10) ;
//i = new Integer(100) ;//报错
开发中自定义常量:
public static final 数据类型 变量名
final修饰基本数据类型和修饰引用数据类型的区别
final修饰的基本数据类型,基本数据数据值不能再改变!
final修饰的引用数据类型,当前不能再开辟堆内存(不能 new ),里面的成员变量依然可以进行赋值
final、finalize、finally的区别
final是一个状态修饰符,最终的、无法更改的!
修饰类,该类不能被继承
修饰成员方法,该成员方法不能被重写
修饰变量,此时变量是一个常量
finalize:是一个方法名,是后面jvm当前确定堆内存中对象没有更多引用的时候,通过立即回收器来调用进行回收的方法!
finally:是关键字,是后面java中去处理“异常”的一种格式:捕获异常
标准格式
try{
//可能出现问题代码
}catch(异常类型 变量名){
处理异常
}finally{
//释放相关的系统资源
}
三、多态
1.概念
从宏观角度去说:一个事物(能看到真实存在)体现出的不同形态!
从内存角度去说:一个对象它的所在类型的变化
使用多态的前提条件:
1)必须存在继承关系,才能使用多态!
2)必须存在方法重写,子类继承父类部分功能将父类重写
3)必须存在父类引用指向子类对象---->多态的“向上转移”
class 父类名{}
class 子类名 extend 父类名{}
//多态测试...
父类名 对象名 = new 子类名();
2.多态的成员访问特点
成员变量:编译看左,运行看左!
成员方法(默认 非静态):如果子类重写了父类的方法,编译看左,运行看右!
静态方法:算不上重写,和静态的都是类成员!(访问方式都是类名来调用的)
构造方法:继承是多态的前提条件!所以在使用父类引用指向子类对象,还有遵循“分层初始化”
先让父类构造初始化,然后再是子类构造初始化!
3.多态的好处
1)可以提高代码的复用行(由继承保证)
2)可以提高代码的扩展性(健壮性)--->有多态保证
4.多态的弊端
不能访问子类特有方法,通过向下转型来访问,这种方式节省内存;但是向下转型不当,会出现运行时期异常
不能子类访问特有方法如何解决
1)直接创建具体的子类对象 子类名 对象名 = new 子类名();
虽然可以,但从内存考虑:消耗资源,浪费空间,又需要去开辟堆内存!
2)多态本身:父类引用指向子类对象,能不能将父类的引用转换成子类型
“向下转型”--->强转类型转换的格式,前提必须有“向上转型”
数据类型 变量名 = (目标数据类型)(初始化值或者表达式);
5.静态变量和成员变量的区别
1)内存位置不同
静态变量:随着类的加载而加载,存储在方法区的静态区中
成员变量:在对内存中(对象成员)
2)生命周期不同
静态变量:随着类的加载而存在,随着类的加载完毕而初始化完毕
成员变量:随着对象的创建而存在,随着对象的创建完毕等待垃圾回收器空闲的时候回收而消失!
3)初始化不同
静态变量:系统默认初始化,然后再根据对象名调用,进行显示初始化
成员变量:初始化实际随着类的加载而初始化,被静态修饰,可以被多个对象共用!
6.abstract关键字
抽象:有抽象的方法必须为抽象类
抽象类中不一定都是抽象方法!(部分的功能,抽象功能,必须让子类重写!)
抽象方法(成员方法)的格式:
权限修饰符 abstract 返回值类型 方法名(空参/带参)
抽象的本质:强制子类必须将父类的所有的抽象方法,必须实现(重写)
抽象类的特点:
1)不能实例化(不能new 创建对象)
2)抽象类的子类一定有具体类,否则无法进行实例化!
抽象成员的特点:
1)成员变量:可以是变量,也可以是自定义的常量
2)成员方法:既可以有抽象方法,也可以有非抽象方法
3)构造方法:还存在继承关系,分层初始化(先父类构造初始化,然后是子类构造初始化)
无法构造方法/有参构造方法都可以存在,目的都是为了数据进行初始化!
抽象abstract关键字不能和哪些关键字共存
abstract不能和private共用:
被private修饰的只能在当前类访问,而abstract修饰的方法,它需要强制子类进行重写;
abstract不能和static共用:
abstract修饰的成员方法,需要被子类重写,还是抽象多态进行实例化;而static随着类的加载而加载,跟类相关的!
abstract不能和final共用:
被final修饰的成员方法不能被重写,而abstract修饰成员方法,强转子类重写!
abstract:用在类上,标记这个类----抽象类
用在方法上,标记这个方法是抽象方法(结合public使用居多)
7.接口
接口:提现的是这个事物本身不具备的功能,是一种额外的扩展功能!
只要这个事物实现了接口,他就具备这个功能!
java定义接口
interface 接口名{}
接口的子类(子实现类) implements 接口名{
强制子实现类必须将接口中所有抽象方法必须重写!(实现)
}
接口的特点:
1)接口不能实例化(不能创建对象)
2)接口如何实例化?
接口多态
接口名 对象名 = new 接口的子实现类名();
(前提:子实现类是非抽象的,是一个具体类)
开发中:
接口名和子实现类的命名规范(开发项目中)
举例:
接口名: interface Inter{}
接口的子实现类命名: 接口名 +Impl
class InterImpl implements Inter{}
接口中成员的特点:
成员变量:只能是常量 存在默认修饰符 publik static final
成员方法(默认 非静态):只能是抽象方法,存在默认修饰符 public abstract
在接口中是可以定义静态方法,必须有方法体(特例)
构造方法:没有构造方法
因为子实现类和接口的关系是implements实现关系,只是将接口暴露的额外功能进行实现!
在java中,
类与类:继承关系,extebds,只支持单继承,不支持多继承,但是可以多层继承
类与接口:实现关系,implement,而且一个类继承另一个类的同时,是可以实现多个接口!
接口与接口之间逗号隔开
接口与接口:继承关系,extends,不仅支持单继承,也支持多继承,也可以多层继承!
抽象类与接口的区别:
1)成员区别
抽象类:
成员变量:可以为变量,也可以为自定义常量
构造方法:有参/无参构造方法都存在,目的为了给类的成员进行初始化,分层初始化
成员方法:即可以有抽象方法,也可以有非抽象方法
接口:
成员变量:只能是常量,存在默认的隐藏的修饰符 public final static
构造方法:没有
成员方法:只能是抽象方法
2)关系的区别:
类与类:继承关系,extends-->只支持单继承,不支持多继承,可以多层继承
类与接口:实现关系,implements-->一个类继承另一个类的同时,可以实现多个接口,
接口名和接口名逗号隔开
接口与接口:继承关系,extends-->支持单继承,多继承,多层继承!
3)设计理念
抽象类:继承关系,体现核心思想"is a" 的关系,类A是类B的一种或者类B是类A的一种
接口:子实现类和接口实现关系----体现核心思想 "like a"的关系,是事物的额外的扩展功能!
方法的形式参数问题:只研究引用类型
方法形式参数:
具体类:调用该方法,此时实际参数需要的是当前类的对象
抽象类:调用该方法,此时实际参数需要的是当前抽象类的子类对象
接口类型:调用该方法,此时实际参数需要的是接口的子实现类对象
开发中:方法形式参数是具体类以及皆苦情况居多!
研究方法的返回值引用类型:
方法的返回值如果是引用类型:
具体类:需要返回该具体类的对象!
抽象类:需要返回该抽象类的子类对象!
接口:需要返回接口子实现类对象!
四、包
包---package存储本地Java代码的一个目录(文件夹)
开发中,包(字母全部小写,分包使用.隔开)有代码分层的含义 :
单级包
com
xxx.java
多级包(推荐)
com.qf
com
qf
xxx.java
domain :存储的实体类(描述现实世界事物的)
service(业务服务层): 存储的业务接口
dao(数据访问层:Data Access Object:数据访问对象):数据访问接口
impl:针对数据访问接口的实现层
utils:工具类-->存储的都是通用的工具类的代码 xxx.java文件
test:存储的测试接口中的功能代码
权限修饰符的范围
在同一个包下的同一个类中在同一个包下的子类中/同一个包下的无关类中不同包下的无关类中
private私有Y
默认修饰符YY
protected受保护的YYY
public公共的YYYY
五、内部类
内部类:在Java中,在一个类中定义另一个类
分类:
1)成员内部类:
在外部类中,在外部类的成员方法外
特点:
可以访问外部类的成员包括私有!
直接去访问外部类的中的成员内部类的成员方法:特有方式 (成员内部类没有private以及static修饰!)
外部类.内部类名 对象名 = new 外部类名().new 内部类名() ;
成员内部类所涉及到的修饰符的问题:
有的时候不想让外部类直接去访问内部类的成员,为了保证内部类的成员安全,加入private
成员内部类可以使用过static修饰:
特点:静态的成员内部类它里面的所有 成员方法:
无论是静态的方法还是非静态的,访问外部类的成员:必须先为静态
想直接去访问静态的成员内部类的这些成员方法:
外部类名.内部类名 对象名 = new 外部类名.内部类名();
2)局部内部类:
在外部类的成员方法中定义
特点:
局部内部类也是可以直接访问外部类的成员变量,包括私有!
匿名内部类
匿名内部类:(没有名字的类)---是内部类的一种简化格式!
针对抽象类或者接口去使用
匿名的格式:
new 类名(抽象类)或者接口名(){
重写类里面或者接口的抽象功能
};
应用范围:在局部位置中使用
匿名内部类的本质:
是继承了该抽象类或者是实现了接口子类对象!