1-8 面向对象之封装

回顾

面向编程思想:所有事物触发的原则是对象,找到这个对象身上具备的【属性和行为】,描述对象需要通过类,类中就定义着属性和行为【成员变量和成员方法】,如果要通过类构建对象,就需要提供对象构造方法,构造方法分为常用的两种,一种是无参构造方法【方法的参数列表中没有任何参数】,另外一种是有参构造方法【方法参数列表中定义参数,原则是类中有哪些成员变量,形参列表就和成员变量一致,还可以选择性的提供初始化变量】,类中构造方法是允许重载的

如何在代码中创建类和对象

1.创建类
  访问权限修饰符  class  类名{
    	成员变量  --> 对象的属性
        构造方法  --> 对当前创建对象的一种方式,除了创建对象之外,还可对属性进行初始化
        成员方法  --> 对象的行为     
   	   
  }


2.创建对象
 类名  对象名 = new  类名();
PS: new 后面 类名() 其实就是在调用构造方法
    
3.如何在类中定义构造方法
    3.1 无参构造方法
     public 类名(){
         对属性进行初始化操作,所有调用无参构造方法对象,都会有这个默认属性赋值
         调用一些其他方法,这样做比较少
         还可以this关键字和Super关键字   
     }
   public 类名(和属性类型一致的参数列表){
         对属性进行初始化操作,根据创建对象的不同动态的存储每个不同对象属性初始值
         调用一些其他方法,这样做比较少
         还可以this关键字和Super关键字   
     }
 PS: 如果类中没有明确的提供构造方法, 系统会默认提供一个午无参构造方法
     如果类中明确提供构造方法,此时系统提供的无参构造将不能再调用
 
 4.成员变量和成员方法
     
   类中定义成员变量其实就是之前的【全局变量】,成员变量可以使用权限修饰符,有默认值,默认值和数据类型有关
   类中定义成员方法其实就是原有静态方法 去掉static
   访问权限修饰符 返回值类型 方法名(参数列表){
    		方法体
             return
 	}
     
PS: 成员变量和成员方法是够可以添加static关键字?
      是可以的,但是含义完全变了,添加了static关键字之后会成为类属性和类方法,而不是单独属于某一个对象
      所以如果明确是成员变量和成员方法,就不要添加static关键字。
    
    如何调用成员变量和成员方法?
     调用成员变量  --> 对象名.成员变量名
     调用成员方法  --> 对象名.成员方法名()
   PS: 这种调用方式是因为,不在描述类中,是在另外一个类中调用 
    

作业

package com.qfedu.HomeWork;
//狗类狗具有属性(姓名,年龄,性别,种类)和行为(吃,喝,咬人)
//对类进行了一个区分:描述对象的 --》这个类就是描述类或实体类 --》 这个类中是不写main方法
public class Dog {
    //定义对象属性 --> 成员变量
    String name;
    int age;
    char gender;
    String kind;
    //提供外部创建Dog类对象的方式 --》 构造方法
    public Dog(){}
    //形参的类型和属性的类型,形参顺序和属性顺序是一致
    public Dog(String n,int a,char g,String k){
        //通过形参对实行属性进行赋值
        name = n;
        age = a;
        gender = g;
        kind = k;
    }
    public void eat(){
        //成员变量,除了在外部【当前类之外】,需要使用对象名.属性名
        //在类的内部可以直接在成员方法中使用,不需要使用任何关键字和修饰
        System.out.println(name + "吃什么。。。。");
    }
    //喝和 咬人就可完全仿照上面这个方法定义即可
}

如果在一类中需要使用到另外一个类的属性和行为?

"第一种方式":在使用类中,将另外一个类的对象作为当前类属性存在【必须满足客观现实规律】
            好处:因为是在了中定义属性即成员变量,所以可以直接在整个类中使用【使用范围广泛】
            坏处:需要满足客观现实规律
    
设计一个电脑类, 属性: CPU, 主板, 硬盘, 内存, 显卡
		         CPU/主板/硬盘/内存/显卡 都是单独的类, 属性: 名称/价格
	     电脑类方法: 计算这个电脑的价格    
package com.qfedu.HomeWork;

public class CPU {
    String name;
    int price;
    public CPU(){

    }
    public CPU(String n, int p){
        name = n;
        price = p;
    }

}

public class Xianka {
    String name;
    int price;
    public Xianka(){

    }
    public Xianka(String n, int p){
        name = n;
        price = p;
    }

}

public class YingPan {
    String name;
    int price;
    public YingPan(){

    }
    public YingPan(String n, int p){
        name = n;
        price = p;
    }
}

public class Zhuban {
    String name;
    int price;
    public Zhuban(){

    }
    public Zhuban(String n, int p){
        name = n;
        price = p;
    }

}

public class NeiChun {
    String name;
    int price;
    public NeiChun(){

    }
    public NeiChun(String n, int p){
        name = n;
        price = p;
    }
}

//电脑
public class Computer {
    //CPU, 主板, 硬盘, 内存, 显卡
    CPU cup; //对于外部而言 CPU是一个类,对于Computer而言他是一个属性【成员变量】
    //这个CPU属性就相当于是 CPU cpu = new CPU("i790000",1000);
    Zhuban zb;
    YingPan yp;
    NeiChun nc;
    Xianka xk;
    public Computer(){}
    public Computer(CPU c,Zhuban z,YingPan y,NeiChun n,Xianka x){
        cup = c; //  c = new CPU("i790000",1000)
        zb = z;
        yp = y;
        nc = n;
        xk = x;
    }
    public void addMoney(){
        int sum = cup.price+zb.price+yp.price+nc.price+xk.price;
        System.out.println("电脑的价格:"+sum);
    }
}

"第二种方式":在使用类中,创建一个方法,方法的参数是需要使用类的对象【即使用类是以方法参数存在】
           好处: 什么地方用就写在什么位置,并且不受客观现实规律影响
           坏处: 作用域范围小【仅限当前方法内部使用】
  
    
通过构造方法,初始化一个四开门白色宝马,模拟一个场景富二代,炫耀自己的车 
   富二代对象 --> 行为 介绍自己的
package com.qfedu.HomeWork;

public class Car {
    int door;//车门
    String color;//颜色
    public Car(){}
    public Car(int d,String c){
        door = d;
        color = c;
    }
}
/**
 * 富二代
 */
public class Person {
    String name;
    public Person(String n){
        name =n;
    }
    //Car是不能成为当前Person属性,但是又要用到car的信息
    public void showInfosCar(Car car){
        System.out.println(name+"在介绍自己的车:"+car.color+" "+car.door);
    }
}

    

PS:在一个类使用另外一个类的属性或方法时,当前这两种形式叫做 --》【类的复合】

图书管理员

package com.qfedu.HomeWork2;

/**
 * 图书管理员类
 */
public class LibraryManager {
    //属性
    String name;
    public LibraryManager(){}
    public LibraryManager(String n){
        name = n;
    }
    //行为 需要限制传入参数
    public String checkCardType(Student stu){
       return stu.cardType == 'A' ? "《金庸全集》" : "《十万个为什么》";
    }
}
package com.qfedu.HomeWork2;

/**
 * 创建学生
 */
public class Student {
    String name;
    char cardType;
    public Student(){}
    public Student(String n,char ct){
        name = n;
        cardType = ct;
    }
    public void borrowBook(){
        System.out.println("在一个风雨交加的夜晚"+name+"独自一个人走在去图书馆的路上.....");
    }
}

小明交换牌

/*
牌的类
 */
public class Poker {
    //属性 有点数 和 花色
    String color; // 牌的颜色【花色】
    String num;// 牌的点数【因为有 J Q K A】
    public Poker(){}
    public Poker(String c ,String n){
        color = c;
        num = n;
    }
}
/**
 * 手类
 */
public class Hand {
    //属性
    Poker poker ;//将牌作为手的属性存在【手中有牌】
    String type;//分左右手
    public Hand(){}
    public Hand(String t,Poker p){
        type = t;
        poker = p;
    }
    //设置一个方法拿牌
    public void setPoker(Poker p){
        poker = p;
    }
}
package com.qfedu.HomeWork2;
/*
 人
 */
public class Person {
    //属性 人分左右手
    /*
     首先Hand类对于Person而言是Person属性,本质上leftHand和rightHand都是Hand类的对象
     既然是对象就可以用过leftHand这个对象.获取Hand类中成员变量和成员方法
     而Hand类中 存在一个Poker类的实行即Poker类的对象
     所以通过leftHand调用自身Hand类中poker属性,就可以获取到牌的颜色和点数
                                  中type属性,就可以获取到是左手还是右手
     */
    Hand leftHand;
    Hand rightHand;
    public Person(){

    }
    public Person(Hand left ,Hand right){
        leftHand = left;
        rightHand = right;

    }
    //交换牌
    public void swapPoker(){
        //可以先获取手上的牌
        Poker leftPoker = leftHand.poker;
        Poker rightPoker = rightHand.poker;
        leftHand.setPoker(rightPoker);
        rightHand.setPoker(leftPoker);
    }

    //展示牌
    public void shwoInfosPoker(){
        //获取手中的牌
        Poker leftPoker = leftHand.poker;
        Poker rightPoker = rightHand.poker;
        System.out.println(leftHand.type+"手拿的牌是:"+leftPoker.color+""+leftPoker.num);
        System.out.println(rightHand.type+"手拿的牌是:"+rightPoker.color+""+rightPoker.num);
    }

}

public class Test {
    public static void main(String[] args) {
        
        //2.交换牌测试
        //初始化牌的对象
        Poker aPoker = new Poker("红桃","A");
        Poker bPoker = new Poker("方片","K");
        //初始化手
        Hand leftHand = new Hand("左",aPoker);
        Hand rightHand = new Hand("右",bPoker);
        //初始化人
        Person xiaoming = new Person(leftHand,rightHand);
        //展示
        System.out.println("-------------------------小明没有交换牌之前----------------------------");
        xiaoming.shwoInfosPoker();
        System.out.println("-------------------------交换牌----------------------------");
        xiaoming.swapPoker();
        System.out.println("-------------------------小明交换牌之后----------------------------");
        xiaoming.shwoInfosPoker();


    }
}



在某同学的电脑中有一个文件夹,文件中存储着1000部学习视频。

问题1:当前文件夹中出现相同视频名称时候,如何处理?修改名字【致命弯道1-5】

问题2:突然间,需要在1000部学习视频中找到某一部视频,忘记名字了,但是记住了内容?

提供一种管理方式,根据不同视频内容进行分类【在创建出多个文件夹】

爱情、惊悚、动作、科幻、剧情、喜剧、学习资料…存着不同视频方便进行管理

如果在开发中,加入我们有1000个源文件,同时在src中创建,就需要对其进行一个管理操作,这个管理操作就是创建【包】

包:可以用来区分【分类】不同Java源文件,以达到对源文件管理的目的,不同包中允许存在相同类名

如何定义包?

1.创建包的时候不能以【Java】开头,因为Java有安全检查机制【Java开头的包是系统API】

2.包名必须遵守标识符命名规则,不能使用关键字【可以因情况而定】,建议全部的名称小写

3.在开发中包的名称是公司域名倒写【不包括www】

例如:

www.qfedu.com 公司的域名
    
创建包的名字 :   com.qfedu.项目名称  或 com.qfedu.模块名称    
PS:包名的层级是没有限制,要有实际意义
    com.qfedu.dao.domain
    在windows系统中展示的形式 [当前在工程中点就是系统中路径,包名就是系统中文件夹名称]
    C:\com\qfedu\dao\domain
        
PS: 如果公司域名有数字 例如 www.360.com
     com._360   

面向对象之封装

PS:封装的本质就是不对外暴露实现过程,而是提供一个调用方法,外部无需知道内部是如何实现,只需要知道如何使用即可,这种方式就已经是封装了。

需求: 1.创建一个Cat,提供属性【姓名和年龄】,在创建一个测试类Cat进行属性赋值

package com.qfedu.block;
/*
cat类,提供属性 姓名和年龄
 */
public class Cat {
    String name;
    // 成员变量有两个特点 一个就是可以使用权限修饰符  另外一个是有默认值
    // 现在已知权限修饰符只有一个public 公有权限,代表所有的人都可进行访问【是最大权限】
    //  另外一个是default默认权限--》 也叫做包【package】权限,在整个包内部都可以访问
    // 任何可以使用权限修饰符的 不写权限修饰符 默认就是包权限
    // 为了保证成员变量安全,不提供直接外部对成员变量的方法,可以对成员添加权限修饰符
    // 最低权限  --> private 私有的  --》一旦使用这个权限修饰符,修饰仅限当前了【类中可以访问】
    private int  age;
    public Cat(){

    }
    public Cat(String n, int a){
        name = n;
        age = a;
    }
}

package com.qfedu.block;

public class CatTest {
    public static void main(String[] args) {

        //1.正常创建对象
        Cat cat = new Cat();
        //通过cat对象调用成员变量赋值和取值操作
        //cat.age  = 1;
        //此时这样做合理吗?
        /*
        如果从语法角度而言,合理。因为age是int类型 即可以存储 正整数 也可以存储 负整数
        如果从客观现实规律来看,不合理,因为猫是不能出现负数年龄
        这里会暴露出一个问题,只要通过Cat类创建对象,就可以对age属性任意修改
        外界可以对成员变量的值肆意修改,造成变量数据不安全,在实际开发中
        我们是严禁外部直接调用成员变量--》此时就需要将成员变量封装起来
        在java中封装特性最有利的体现就是 ---》 属性私有【成员变量私有化】
         */
        cat.age = -10000;
        cat.name = "小花";
        System.out.println("猫的名字:"+cat.name+"猫的年龄:"+cat.age);

    }
}


总结:通过private私有化权限修饰符,体现了面向对象中封装的特性,保证了成员变量不对外直接访问的途径,这样一来成员变量就安全了,但是随之而来的是对变量操作不在向以前一样方便,如果操作的时候不进行赋值,只访问但是现在也是被禁止的,如果属性私有化了如何提供合理化访问方式?

如果属性私有化如何提供对外访问操作Getter和Setter

Getter和Setter方法

因为为了保证属性安全,对属性提供限制访问权限修饰符【private】确实可以做属性无法提供对访问,但是在实际应用,如果值打印不赋值或只赋值不打印,即想打印也想赋值,私有化属性是满足封装概念,这个概念这满足了一半,剩余通过其他方式间接操作封装属性,可以使用【Getter和Setter方法】

我们是通过Getter方法获取到属性值,Setter方法是对属赋值

PS:Getter和Setter不是必须要成对出现,可以根据实际的需求,选择性提供。

Getter方法

Getter方法的主要作用【获取】当前私有属性的值
    
访问权限修饰符 返回值类型 方法名(){
    return  对应的私有化成员变量
}    
ps:
    "1.一般Getter和Setter的出现主要是伴随着私有化属性出现"
    "2.因为属性已经私有化,所以这类Getter方法一般是使用public 作为权限修饰符"
    "3.因为Getter方法是获取私有属性值,所以必须有返回值类型,这个返回值类型取决于获取私有属性的数据类型"
    "4.这个方法的名称是固定是 【get属性名】  例如: private String name -->方法名就是 getName"
    PS:如果是boolean类型私有成员变量,get方法名字是 【is属性名】
    "5.Getter方法一般是没有参数列表,因为他是获取值,所以不会进行参数定义并且这个模式是固定"
    "6.return 必须写,因为有返回值类型,除此之外Getter是获取属性"

Setter方法

Setter方法的主要作用是对【属性进行赋值】私有属性
   
访问权限修饰符  void 方法名(参数列表){
 	使用参数列表中形参对私有化成员变量进行赋值   
}
PS:
    "1.一般Getter和Setter的出现主要是伴随着私有化属性出现"
    "2.因为属性已经私有化,所以这类Setter方法一般是使用public 作为权限修饰符"
    "3.因为Setter方法是对私有属性赋值,所以没有返回值类型即void,并且是这个是固定的"
    "4.这个方法的名称是固定是 【set属性名】  例如: private String name -->方法名就是 setName,boolean类型不受影响"
    "5.必须有参数列表,参数列表中定义形参与要赋值的私有属性是一致"
    "6.Setter方法是没有return关键字,也不建议添加"
    
注意:现在属性是私有化的,外部是无法直接访问,只要提供了getter和setter方法之后才能个对实行进行操作,获取属性值没有什么问题,但是开放赋值后,还会出现赋值错误, 例如age赋值为-1 ,这样一来封装性就没有了,此时应对策略【非法拦截】,在setter方法中对要赋值的属性进行非法拦截操作,以到大属性安全目的。

package com.qfedu.block;
/*
cat类,提供属性 姓名和年龄
 */
public class Cat {
    String name;
    // 成员变量有两个特点 一个就是可以使用权限修饰符  另外一个是有默认值
    // 现在已知权限修饰符只有一个public 公有权限,代表所有的人都可进行访问【是最大权限】
    //  另外一个是default默认权限--》 也叫做包【package】权限,在整个包内部都可以访问
    // 任何可以使用权限修饰符的 不写权限修饰符 默认就是包权限
    // 为了保证成员变量安全,不提供直接外部对成员变量的方法,可以对成员添加权限修饰符
    // 最低权限  --> private 私有的  --》一旦使用这个权限修饰符,修饰仅限当前了【类中可以访问】
    private int  age;

    //getter和setter方法
    //获取方法---》 getter
    public int getAge(){
        return age;
    }
    //对属性赋值 ---》setter
    public void setAge(int age){
        if(age >= 0) {
            //编译阶段是通过的,执行阶段也能过
            //但是如果这样写,age并没有发生改变,此时形参名和属性名一致
            //编写赋值语句的时候 age = age 发生一个就近原则 【当前变量离谁最近就是谁】
            //即当前这个两个age其实都是形参,不会给属性赋值的
            //此时就需要避免形参名和属性名一致,一般为了提示操作方法的人员参数是什么,参数名【变量】都会
            //起的有意义,有没有什么办法可以让形参名和属性名一致并且可以赋值
            //有处理方案,这个方法也是这个关键字唯一的作用 ,这个关键字就是this
            this.age = age;
        }else{
            System.out.println("赋值参数不合法!");
           
        }
    }

    public Cat(){}

    public Cat(String n, int a){
        name = n;
        age = a;
    }
}
package com.qfedu.block;

public class CatTest {
    public static void main(String[] args) {

        //1.正常创建对象
        Cat cat = new Cat();
        //通过cat对象调用成员变量赋值和取值操作
        //cat.age  = 1;
        //此时这样做合理吗?
        /*
        如果从语法角度而言,合理。因为age是int类型 即可以存储 正整数 也可以存储 负整数
        如果从客观现实规律来看,不合理,因为猫是不能出现负数年龄
        这里会暴露出一个问题,只要通过Cat类创建对象,就可以对age属性任意修改
        外界可以对成员变量的值肆意修改,造成变量数据不安全,在实际开发中
        我们是严禁外部直接调用成员变量--》此时就需要将成员变量封装起来
        在java中封装特性最有利的体现就是 ---》 属性私有【成员变量私有化】
         */
        //cat.age = -10000;
        //如果对属性进行赋值,需要使用setter
        cat.setAge(-1);
        cat.name = "小花";
        //在外部调用时候是直接调用 get方法获取属性,而非直接操作属性
        System.out.println("猫的名字:"+cat.name+"猫的年龄:"+cat.getAge());

    }
}


总结:

在创建一个类需要使用如下方式完成

  public class 类名{
     private 成员变量
     有参和无参构造方法
     需要提供需求中所需要的getter和setter方法【固定全写】
     成员变量    
  }

思考问题:创建一个功能(方法)保存所有联系人的信息

void save(String name,int age,String phoneNumber,String email,String QQNumber...)
    因为当前方法可以用来保存联系人,但是随着信息的越来越多,我们参数将会越来越长,不好管理,需要传递信息过多,此时我们是不是可以将联系人信息看做时一个整体,进行的统一的管理,当前我们只需要对联系人信息进行一个统一的存储封装,只需要提供联系人信息就可以传递这个参数了,可将这个参数封装到类中,
class LinkMan{
    String name;
    int age;
    String phoneNumber;
    String email;
    String QQNumber;
    
}
void save(LinkMan man)

封装的概念:

封装是面向三大特征之一:主要作用就是将**【信息隐藏】起来,把不需要外界知道信息隐藏,尽可能隐藏对象功能实现的细节,向外直接提供可以访问的方法,保证外界无法破坏内部的信息,这就是【封装】**

this关键字

PS: this关键字代表的式【当前对象】–》【谁调用谁就是,谁触发属性或谁触发这个方法谁就是当前对象】

总结:this 关键字的最大作用,就是区分形参名和属性名
    
     this 关键字可以用来在类中调用【成员变量】和【成员方法】
     this 关键字调用成员变量  --- 》 【this.成员变量名】 即可以完成取值操作也可以完成赋值操作
     PS:现在使用this关键字调用成员变量唯一目的就是【区分形参名和成员变量】
         如果在一个方法中,没有重名的问题
         this.成员变量 完全等价于 成员变量
    private String name;
    public void showInfosName(){
        System.out.println(this.name);
        //和这样写没有任何区别 ,所以this关键字可以省略不写
        System.out.println(name);
    }

    this 关键字调用成员方法 ---》 【this.成员方法(参数列表)this.成员方法  和  成员方法 效果是一样   
      public void display(){
        this.show();
        //和这样写完全没有区别,所以this关键字可以省略不写
        show();
    }

    this 关键字 可以在构造中调用另外一个构造方法,必须写在第一句,不能自己调用自己
     public ThisDemo() {
        //this("大家好"); //调用自己的有参构造方法,而且必须在第一句,只能在构造方法中使用
    }
    public ThisDemo(String n){
        //this(); //调用自己的无参构造方法,而且必须在第一句,只能在构造方法中使用
        name = n;
    }
    这个方法近乎不用,会被super关键字代替
        
    this 关键字可以当做参数传递  谁调用谁就是这个this,传递的就是调用方法的对象 
        
    作用:写有参构造方法和set方法时,如果形参名和属性名一致,使用this关键字来区分名字即可    
    public ThisDemo(String name){
        //this(); //调用自己的无参构造方法,而且必须在第一句,只能在构造方法中使用
        this.name = name;
    }    
    

类版本方法参数传递

package com.qfedu.valueAndaddress;

/**
 * 类版本的参数传递
 */
public class StudentDemo {
    public static void main(String[] args) {
        Student stu = new Student("李逵",30);
        //值传递
        System.out.println("过年前:"+stu.getName()+"年龄:"+stu.getAge());
        System.out.println("----------------------------过年了------------------------------");
        //过年岁数要+1
        addAge(stu.getAge());//这个方法出就是典型的值传递,没有任何引用个传递在里面,相当于将存在堆空建中age的值取出拷贝复制给
        //在栈中开辟空间addAge方法的形参age 此时相当于是age获取到一个副本所以,这个计算方式就是一个典型值传递,所以是无法更改的
        System.out.println("过年后:"+stu.getName()+"年龄:"+stu.getAge());



        //引用传递
        System.out.println("过年前:"+stu.getName()+"年龄:"+stu.getAge());
        System.out.println("----------------------------过年了------------------------------");
        //过年岁数要+1
        addAge(stu);
        System.out.println("过年后:"+stu.getName()+"年龄:"+stu.getAge());

        //改名
        System.out.println("过年前:"+stu.getName()+"年龄:"+stu.getAge());
        System.out.println("----------------------------过年了------------------------------");

        changeName(stu);
        System.out.println("过年后:"+stu.getName()+"年龄:"+stu.getAge());



    }
    // String 被称为不可变字符串 ,因为每次对字符赋值的时候都会重新创建一个新的地址
    public static void changeName(String name){ //将student中name的地址出传递给了形参 String name = stu.getname()
        System.out.println("形参name在没有修改之前获取的值是:"+name);
        name = "李鬼";//修改原有行啊 name的地址 ,形参name改名了 但是student对象中的name没有改变
        System.out.println("形参name在修改之后获取的值是:"+name);

    }
    public static void changeName(Student stu){
        stu.setName("李鬼");
    }





    public static void addAge(Student stu){
        int age = stu.getAge()+1;
        stu.setAge(age);
    }

    public static void addAge(int age){
        age += 1;
    }
}


Static关键字

static是一个关键字,可以用来修饰变量和方法【变量不能是局部变量】

static关键字的特点:

1.static关键字修饰完的属性和方法是属于【类】的

2.static修饰的属性和方法,会随着类的加载而加载

PS:当类加载器把字节码文件加载到JVM中时,static修饰的变量和方法就已经被加载到内存中了

3.优先于对象而存在的

PS:因为对象是new出来,前提是有类,有类的时候就已经有静态属性和方法

4.static修饰变量是**【所有对象共享】**,它不属于任何一个对象,它是属于类的即所有所有对象

5.static修饰变量和方法需要使用【类名.静态变量】 和【类名.静态方法】进行调用

PS:如果在同一个类中调用,可以省略类名直接调用即可

static修饰的变量和方法

package com.qfedu.Static.varAndMethod;

/**
 * 静态方法和静态属性【变量】的使用
 */
public class StaticVarAndMethod {
    //静态变量可以使用权限修饰符,并且存在默认值 ,是根据不同数据类型所改变
    //整数【0】 小数【0.0】 char【不可见空字符】 boolean【false】 引用类型【null】
    //只能在类中定义【现阶段】
    static int age;
    //成员变量
    String name;
    
    //成员方法
    public void display(){
        System.out.println("我是成员方法");
        //成员方法中是可以直接调用成员变量和其他成员方的
        System.out.println(name);//成员变量
        showInfos(); //成员方法
        System.out.println(this.name);//还可以使用this关键字
        //成员方法调用静态变量和静态方法【演示是在同一个类中,省略了类名,如果是不同类不能省略类名】
        System.out.println(age);//静态变量
        show();//静态方法
        
    }
    public void showInfos(){}
    
    public static void show2(){}
    //静态方法
    public static void show(){
        System.out.println("我是静态方法");
        //静态方法中调用静态变量和静态方法
        System.out.println(age);//静态变量
        show2();//静态方法
        //静态方法调用成员变量和成员方法
        //System.out.println(name);//不能直接调用成员变量
        //showInfos();//不能直接调用成员方法
        //System.out.println(this.name);//this关键字也不能再静态方法中使用
        //因为静态是优先于对象存在的,所有静态方法中是无法直接调用成员变量和成员方法
        //如果要调用,需要使用如下方式
        StaticVarAndMethod  vm = new StaticVarAndMethod();
        System.out.println(vm.name);
        vm.showInfos();
        
    }
}


共享变量

package com.qfedu.Static.varAndMethod;

public class Test {
    public static void main(String[] args) {
        //调用静态变量age并赋值
        StaticVarAndMethod.age = 1;

        StaticVarAndMethod vm1 = new StaticVarAndMethod();
        StaticVarAndMethod vm2 = new StaticVarAndMethod();

         //静态变量是所有对象共享,静态变量是不属于任何而是类的,所以不建议明确使用对象调用静态变量
        //静态只有类才可以调用
        System.out.println("通过vm1对象对静态变量age进行修改.....");
        vm1.age = 100;
        System.out.println("通过vm2对象打印静态变量age的值是:"+vm2.age);
        
      

    }
}


staitc修饰的代码块

PS:静态代码块只会被执行一次,当前类创建的时候,就会被加载

什么是代码块?

在这里插入图片描述

在类中或方法中直接使用**【{}】**大括号括起来的就是代码块代码块分三种

1.局部代码块,直接定义在方法体中(了解)

package com.qfedu.Static.block;

/**
 * 局部代码块
 */
public class InnerBlock {
    public static void main(String[] args) {
        int  b = 20;
        //局部代码块
        {
            //定义变量
            int a = 17;
            System.out.println(a);
            //可以访问局部代码块外部的数据
            System.out.println(b);

        }
        //外部是无法直接访问局部代码块变量
        //System.out.println(a);
    }
}


2.初始化代码块(构造代码块)直接定义在类中

PS:每次创建对象的时候都会执行这个初始化代码块

每次调用构造方法之前,都会调用这个初始化代码块

package com.qfedu.Static.block;

/**
 * 构造代码块
 */
public class GoZaoBlock {
    public GoZaoBlock(){
        System.out.println("无参构造方法");
    }
    //初始化代码块
    {
        System.out.println("初始化代码块");
    }

    public static void main(String[] args) {
        new GoZaoBlock();
        new GoZaoBlock();
    }
}


3.静态代码块就是使用staitc修饰的代码块

package com.qfedu.Static.block;

/**
 * 静态代码块
 */
public class StaticBlock {
    public StaticBlock(){
        System.out.println("无参构造方法");
    }
    //初始化代码块执行次数是根据创建多少决定的
    {
        System.out.println("初始化代码块");
    }
    //静态代码块只会执行一次
    static{
        System.out.println("静态代码块");
    }

    public static void main(String[] args) {
        new StaticBlock();
    }
}

执行过程:

静态代码块
初始化代码块
无参构造方法

PS:静态代码块多用于在创建数据库连接时候,来读取资源文件中数据

工具类

在一个项目中会有一些通用的逻辑,会被抽取到一个类中,这个类中定义都是静态方法和静态属性,通过调用这些静态方法就可以执行对应逻辑,提供这样静态方法的类就叫做【工具类】

PS:工具类的特点,不提供对象创建,里面提供的属性和方法都是静态

​ 已经接触过的工具类**【Arrays和Math】**

自己定义工具类的时候,要求名字必须是 XXXXXUtil 或 XXXXTools

工具类和普通类的区别:

1.工具类不同对象创建,所以构造需要私有化

2.工具类方法和属性必须是static修饰

3.工具类中不允许提供main方法

package com.qfedu.Static.Utils;

/**
 * 工具类
 */
public class ArraySortUtil {
    //1.工具类不允许创建对象,构造方法可以使用权限修饰符 一个public 另外一个private
    private ArraySortUtil(){}

    public static void sortArray(int[] arr){
        for(int i =0 ;i<arr.length;i++){
            for(int j = i+1 ;j<arr.length;j++){
                if(arr[i] > arr[j]){
                    int tmp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = tmp;
                }

            }
        }
    }

}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值