day7
private关键字的特点:
被private修饰的成员变量/成员方法,都只能在本类中访问;
外界类不能直接访问,但是可以通过公共方法间接访问
将学生类进行改造
将name,age属性私有化
只能在本类访问,外界要访问,需要通过公共方法访问
赋值/获取值 setxxx()getxxx() (成员方法)封装:
将一个事物的属性,私有化(对外进行隐藏),外界不能直接访问(保证了数据安全性),需要提供对外的
公共访问来访问成员变量!private:
私有的,外界无法访问的,只能在本类中访问
定义学生类
姓名,和年龄两个属性,属性私有化,提供公共访问方法赋值/获取值
吃,睡,学习,玩游戏
按照上面写完之后,
set方法赋值的时候,局部变量n,a:不能满足 ("标识符的规则":见名知意)
将n,a---->name,age
给学生姓名赋值:
public void setName(String name) ;
name = name ;
}
局部变量和成员变量都叫name,如何区分呢? 这个时候Java提供了一个关键字:this
局部变量隐藏了成员变量,使用this关键字来区分
this:代表了当前类的对象的地址值的引用!
class Student{
private String name ;
private int age ;
//setXXX(xxx)方法
//public void setName(String n){
public void setName(String name){
//name = n ;
//name = name ;
this.name = name ; //区分了成员变量和局部变量
}
/*
public void setAge(int a){
age = a ;
}
*/
public void setAge(int age){
//age = age ;
this.age = age ;
}
//getXXX()
public String getName(){
return name ;
}
public int getAge(){
return age ;
}
//eat
public void eat(){
System.out.println("学习饿了,就需要吃饭...") ;
}
public void sleep(){
System.out.println("学习困了,就需要休息") ;
}
public void study(){
System.out.println("学习JavaEE...") ;
}
}
//测试类
class StudentTest{
public static void main(String[] args){
//创建学生类对象
Student s = new Student() ;
s.setName("高圆圆") ;
s.setAge(30) ;
System.out.println(s.getName()+"---"+s.getAge()) ;
s.eat() ;
s.sleep() ;
s.study() ;
}
}
什么是构造方法?
构造方法是一个方法,特殊的方法
1)方法名和类名一致!
2)没有具体返回值类型
3)连void都没有格式:
权限修饰符(public:目前使用居多) + 类名(xx){}构造方法的分类:
无参构造方法
有参构造方法
构造方法作用:
就是为了 给类中的成员变量进行数据的初始化!(构造方法初始化!)
构造方法是可以重载的;
注意事项:
当前我们定义一个类的时候,没有提供任何构造方法,那么系统会默认无参构造方法;
但是,如果我们提供一个有参构造方法,系统不会在提供无参构造方法!(建议永远给出无参构造方法)
一个类的组成:
1)成员变量
2)加入构造方法
无参
有参构造方法
3)成员方法
一个标准类的写法(正式写法)
需求:定义学生类
姓名,和年龄两个属性,属性私有化,提供公共访问方法赋值/获取值
吃,睡,学习,玩游戏
定义学生类,加入新的成员:构造方法
成员变量:属性私有化:name,age
构造方法:
无参构造/有参构造方法
成员方法:setXXX()/getXXX(),吃,睡,学习,玩游戏
给类的成员变量赋值有几种方式:
1)setXXX(xxx) :公共方法赋值
2)类的有参构造方法直接赋值;
class Student{
//属性私有化
private String name ; //姓名
private int age ; //年龄
//无参构造方法(永远给出)
public Student(){
}
//有参构造方法
public Student(String name,int age){//"张佳宁",30
this.name = name ;
this.age = age ;
}
//提供成员方法
//setXXX()getXXX()
public void setName(String name){
this.name = name ;
}
public String getName(){
return name ; //隐藏 : return this.name ; 将this省略了
}
public void setAge(int age){
this.age = age ;
}
public int getAge(){
return age ;
}
//提供其他成员方法
public String study(String className){
return "正在学习"+className;
}
public void playGame(){
System.out.println("学生可以玩游戏...") ;
}
}
//测试类
class Test{
public static void main(String[] args){
//方式1:无参构造方法+setXXX() +getXXX()
Student s = new Student() ;
s.setName("高圆圆") ;
s.setAge(41) ;
System.out.println("学生的姓名是"+s.getName()+",年龄是:"+s.getAge()) ;
String result = s.study("JavaEE") ;
System.out.println(result) ;
s.playGame() ;
System.out.println("----------------------------------") ;
//方式2:有参构造方法+getXXX()
Student s2 = new Student("张佳宁",30) ;
System.out.println("学生的姓名是"+s2.getName()+",年龄是:"+s2.getAge()) ;
String result2 = s2.study("Python") ;
System.out.println(result2) ;
s2.playGame() ;
}
}
形式参数是引用类型和基本类型的区别是什么?
方法的形式参数如果是基本数据类型,形式参数的改变不会影响实际参数
实际参数传递的时候根据基本类型---传递具体的数据值即可!
方法的形式参数如果是引用类型,形式参数的改变会直接影响实际参数!
实际参数传递的时候,如果是数组,需要传递该数组的对象!
如果是类,需要传递该类的具体的对象
类名 对象名 = new 类名() ;
Java提供了一个关键字:static :可以被多个对象"共享,共用"
关于static静态的使用注意事项:
1)非静态的成员方法:
可以访问静态的成员变量,也可以访问非静态的变量!
包括静态方法或者非静态方法
简单记:非静态的可以访问静态的成员/非静态的...
2)静态的方法
静态只能访问静态! (这些静态变量/方法都是跟类相关的!)static关键字的特点:
1)static 随着类的加载而加载 (生命周期----->xxx.class :static相关的都先进内存! )
2)优先于对象存在
类的加载:类名.class (优先的)
对象的创建:类名 对象名 =new 类名() ;
3)不能和this共用!
4)被静态修饰的变量/方法--->(称为 "静态变量","静态方法"):有共享,共用的意思
举例:
水杯中的水 :不能被共用的
饮水机:可以被共用!
5)被静态修饰的变量或者方法,推荐使用的类名访问
类名.静态变量名;
类名.静态方法名() ;
不推荐使用:类名 对象名 = new 类名() ;
对象名.静态变量名;
对象名.静态方法名() ;
数组的工具类
//工具类:就是为了便于程序员使用,使用简单,而且不需要new ,都是将构造方法私有化,外界不能访问
//工具类中所有的功能都是static的(静态) :类名.方法名();
/*
针对数组的操作的功能: 都提供出来
1)遍历
2)最值
3)获取元素角标值
4)冒泡排序...
在每一个功能上加入 文档注释
public class ArrayTool{
//隐藏了:私有化了
private ArrayTool(){
}
/**
这个功能是针对数组的遍历功能,将元素一一获取出来
最终的结果是[元素1, 元素2, 元素3, ...]
@param arr 这个参数是将指定的数组进行遍历
*/
public static void printArray(int[] arr){
System.out.print("[") ;
//遍历数组
for(int x = 0 ; x < arr.length ; x ++){
//判断
if(x == arr.length-1){
System.out.println(arr[x] +"]") ;
}else{
System.out.print(arr[x]+", ") ;
}
}
}
/**
该功能是获取数组中的最大值
@param arr 在指定对数组中查找最大值
@return 返回就是获取的数组中的最大值max
*/
public static int getMax(int[] arr){
//参照物
int max = arr[0] ;
for(int x = 1 ; x < arr.length ; x ++){
if(arr[x] > max){
max = arr[x] ;
}
}
return max ;
}
/**
该功能是查询指定的元素在数组中出现的索引值
@param arr 当前在指定的数组中查找
@param key 要查找的指定的元素
@return 返回查询到的元素在数组中的索引值
*/
public static int getIndex(int[] arr,int key){
//使用假设法
int index = -1 ;
for(int x = 0 ; x < arr.length ; x ++){
//判断
if(arr[x] == key){
index = x ;
break ;
}
}
return index ;
}
/**
这个功能是对数组进行冒泡排序
@param arr 对指定的数组进行排序
*/
public static void bubbleSort(int[] arr){
for(int x = 0 ; x < arr.length -1 ; x ++){
for(int y = 0 ; y < arr.length-1-x ; y ++){
if(arr[y] > arr[y+1]){
int temp = arr[y] ;
arr[y] = arr[y+1] ;
arr[y+1] = temp ;
}
}
}
}
}
代码块的优先级:
静态代码块> 构造代码块>构造方法
静态代码块随着类的加载而加载,由于类就加载一次,静态代码块就执行一次!
什么是代码块,以及代码块的分类
在Java中,使用{}包裹起来的代码,都称为"代码块"
代码块的分类:
局部代码块:
在局部位置(方法定义中){xx},作用, 限定局部变量的生命周期,不能超过这个范围访问
构造代码块:
在类的成员位置中使用{}包裹起来的代码,
作用将多个构造方法中相同的代码存储在构造代码块中,在执行构造方法之前先执行,对数据进行初始化!
特点:每次执行构造方法之前,如果存在构造代码块,优先执行构造代码块,在执行构造方法!
静态代码块:
在类的成员位置:
static{
...
}
静态随着类的加载而加载,类加载一次,静态代码块就执行一次
静态代码块优先执行!
构造代码块,构造方法,静态代码块的优先级
静态代码块(后期使用到:第二阶段:JDBC) > 构造代码块 > 构造方法 !
这些类中共性内容抽取到一个独立的类中,然后让这个独立的类和这些多个类产生一种关系 :"继承" (extends)
格式:
class 父类名{}class 子类名 extends 父类名{}
将多个类的共性内容抽取在一个独立的类中,然后独立的类和这些类产生一种"继承"关系
extends
Java提供的"继承" 特征 的好处:
1)提高了代码的复用性
2)提高了的代码的维护性
3)让类与类之间产生关系 ----- 是 "多态的前提条件"
Java开发原则:
开闭原则(经常使用到: 对修改关闭,对扩展开放)
迪米特原则
接口分离原则
依赖注入原则
...
开发中,设计原则: 都要遵循
"低耦合,高内聚"
耦合:类与类的产生的关系
低耦合:这种关系越少越好! "耦合"----只能避免,不能彻底解决!(Spring框架:IOC 控制反转)
内聚:执行某件事情的能力
高内聚:在一个类中能够完成的事情,不要使用多个类完成事情!
继承的特点:
1)在Java中,类与类之间的继承关系,只支持单继承,不支持多继承!
在别的语言中,可能支持多继承,class 子类名 extends 父类名1,父类名2,..{}
2)在Java中,类与类之间虽然不能 多继承,但是可以 多层继承!
继承中,一个类的组成
1)成员变量
2)构造方法
3)成员方法
在继承中,成员变量访问问题!
1)子类继承父类,如果子类的成员变量名称和父类的成员变量名称不一致的情况:
比较简单,分别访问即可
2)子类继承父类,如果子类的成员变量名称和父类的成员变量名称一致的情况:
a)现在本类的局部位置找,有没有这个变量,如果有就直接使用
b)如果本类的局部位置没有,在本类的成员位置中找,如果有,就使用
c)如果本类的成员位置没有,在它的父类的成员位置找,如果有,就使用
d)父类的成员位置都没有这个变量,压根不存在,就报错!
遵循一个原则:"就近原则"
继承关系中,构造方法的访问
子类继承父类,不能够继承构造方法,但是可以通过super()(等会讲)间接访问父类的构造方法,让父类先进行初始化
子类的所有构造方法都默认访问父类的无参构造方法:子类的每一个构造方法的第一句话:super();
super:代表的是父类的空间标识(代表父类的对象的地址值引用)
为什么要去让父类初始化呢?
因为子类继承父类,
可能会使用到父类的数据!所有必须先让父类初始化,然后子类在初始化(分层初始化)
在写父类的时候:在继承中由于存在默认的访问问题,建议永远给出父类的无参构造方法
子类的所有构造方法都会报错:存在默认访问:子类的所有构造方法都默认访问父类的无参(第一句:super())
解决办法:
1)手动给出父类的无参构造方法
2)在子类的所有构造方法中,间接通过super(xx):访问父类的有参构造方法
3)子类的所有构造方法的一个只要能够让父类初始化即可!(不推荐的!)
执行子类无参构造方法,先执行本的有参构造方法:this(xx)
然后在通过本类的有参构造方法 :super(xx):间接访问父类的有参构造,完成父类初始化
class Fu{
/*
public Fu(){
}
*/
public Fu(String name){
System.out.println("这是父类的有参构造方法") ;
}
}
//子类
class Zi extends Fu{
public Zi(){
//super("随便给") ; //访问父类的有参构造
this("hello") ; //本类的有参构造方法
System.out.println("这是子类的无参构造方法...") ;
}
public Zi(String name){
super("随便给") ;//访问父类的有参构造
System.out.println("这是子类的有参构造方法") ;
}
}
//测试类
class ExtendsDemo4{
public static void main(String[] args){
Zi zi = new Zi() ;
System.out.println("-------------------") ;
Zi zi2 = new Zi("javaee") ;
}
}
继承中的分层初始化
子类继承父类
Zi zi = new Zi() ;-- 子类的构造方法: class Zi extends Fu{}
需要让父类先初始化----先执行父类构造方法,然后才是子类的构造方法!
2)
继承关系中,成员变量访问问题 :如果子类继承父类,成员变量名称都一致, 就近原则
需要现在子类的局部位置找,有就使用
没有,在子类的成员位置找,有就使用
没有,在父类的成员位置找,有就使用
this和super的区别
this:代表的本类对象的地址值引用
super:代表的父类空间标识(父类对象的地址值引用)
this.变量:访问的本类的成员变量
this.方法名():访问的本类的成员方法
this()/this(xx):访问本类的无参构造方法/访问的本类的有参构造方法
super.变量名:访问的是父类的成员变量
super.方法名():访问的父类的成员方法
super()/super(xx):访问的父类的无参构造方法/访问的父类的有参构造方法
final:最终的,无法更改的
* 可以修饰类,该类不能被继承
* ,可以修饰变量,此时这个变量是一个常量:自定义常量
* 此时这个变量只能被赋值一次,再次赋值,报错!
* 可以修饰方法,
* 此时这个方法不能被重写!