面向对象编程的三大特征之一 封装

1、概述

通过对象给成员变量赋值的时候,可以赋值一些非法的数据。这样是不合理不符合现实生活的。 我们应该在赋值之前,做一次判断,数据校验,也就是对即将要赋值的数据做判断。
java就提供了一个关键字:private 私有的(权限修饰符)
注释:
可以修饰成员变量和成员方法,被private修饰的成员只能在本类中访问使用。其他类中使用不了。

因此封装其实就是隐藏对象的属性和相关的实现细节,仅仅对外提供公共的访问方式
获取成员变量值的方法:
1、提供一个公共的方法,打印所有的成员变量值
2、单个使用公共的获取方法,一个一个获取打印
原因:单个使用比一起使用的灵活度要高。
代码示例:

 	//private修饰成员变量
    private String name;
    private int age;
    
 	//打印所有的成员变量值
   	private void show() {
        System.out.println("姓名:" + name + ",年龄:" + age);
    }

规范定义一个手机类的标准版本1.0

class Phone1{
    private String brand;
    private int price;
    private String color;

    public void setBrand(String b){
        brand=b;
    }
    public String getBrand(){
        return brand;
    }

    public void setPrice(int p) {
        price = p;
    }
    public int getPrice(){
        return price;
    }

    public void setColor(String c){
        color=c;
    }
    public String getColor(){
        return color;
    }

    public void show(){
        System.out.println(brand+"---"+price+"---"+color);
    }
}

public class Phone1Demo {
    public static void main(String[] args) {
        Phone1 p1=new Phone1();
        p1.setBrand("小米");
        p1.setPrice(1999);
        p1.setColor("白色");
        //调用方法获取成员变量值
        p1.show();
        //直接输出
        System.out.println("===\r\n"+p1.getBrand()+"---"+p1.getPrice()+"---"+p1.getColor());
        //获取成员变量并打印
        String brand=p1.getBrand();
        System.out.println("===\r\n"+brand);
    }
}

2、this关键字

我们根据见名之意的规范来重新定义形参的名字,运行后发现结果不对,值没有赋上。

public void setName(String name) {
        //局部变量的使用原则:就近原则
        //这里的name采用就近原则后发现,使用的都是形参的变量名name,没有使用成员变量中name.
        //理想上应该是将传进来的name赋值给调用该方法对象中的成员变量name
        //Doctor.name = name;直接通过类名.成员变量的方式目前是不行,我们还没有说过类似的用法,所以这个是有问题的
        //如果这个Doctor对象存在的话,它是不是就表示了一个医生对象
        //如果有一个东西可以代表是当前调用该方法的对象就好了
        //java提供了一个关键字:this
        //this在方法中使用的时候,就代表着调用该方法的对象
        //既然都是一个对象了,我们学过 对象.成员变量
        this.name = name;

定义一个医生类2.0版本

package com.shujia.rx.day09;
/*
定义一个医生类2.0版本
 */
class Doctor{
    //定义成员变量
    private String name;
    private int age;
    private String gender;
    //提供公共getXxx()和setXxx()
    public void setName(String name){
        this.name=name;
    }
    public String getName(){
        return name;//其实这里隐藏了this,可以不写,因为就近原则取得就是对象的成员变量
    }
    public void setAge(int age){
        this.age=age;
    }
    public int getAge(){
        return age;
    }
    public void setGender(String gender){
        this.gender=gender;
    }
    public String getGender(){
        return gender;
    }
    //定义方法输出
    public void show(){
        System.out.println("姓名:"+name+",年龄:"+age+",性别:"+gender);
    }
}
public class DoctorDemo1 {
    public static void main(String[] args) {
        //创建对象
        Doctor d=new Doctor();
        //给成员变量赋值
        d.setName("九昔");
        d.setAge(18);
        d.setGender("女");
        //调用方法输出
        d.show();
    }
}

内存图
在这里插入图片描述

3、构造方法

语句定义格式:
1、方法名与类名相同
2、构造方法是没有返回值的,连void都没有
3、没有具体的返回值

class Student {
    private String name;
    private int age;

    //定义一个构造方法
    Student(){
        System.out.println("这是一个构造方法");
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

public class StudentDemo1 {
    public static void main(String[] args) {
        //创建Student类的对象
        //调用的是无参构造方法创建对象
        Student s1 = new Student();
        Student s2 = new Student();
//        System.out.println(s1.getName()+"---"+s1.getAge());
    }
}

注意:
1、如果我们没有给出构造方法,JVM会自动提供一个无参空方法体的构造方法
2、如果我们给出了一个构造方法,还会提供嘛?
如果我们提供了一个构造方法,系统就不会再提供默认的无参空方法体的构造方法
3、构造方法可以发生重载
给成员变量赋值的方式:
1、使用setXxx(…)的方式给私有成员变量赋值
2、使用带参数的构造方法给私有的成员变量赋值,这里需要与this关键字配合使用

class Construction1{
    private String name;
    private int age;

    Construction1(){
        System.out.println("这是我们自己提供的无参构造方法");
    }

    Construction1(String name){
        System.out.println("这是我们提供的带参数name的构造方法");
        this.name = name;
    }

    Construction1(int age){
        System.out.println("这是我们提供的带参数age的构造方法");
        this.age = age;
    }

    Construction1(String name,int age){
        System.out.println("这是我们提供的带两个参数name,age的构造方法");
        this.name = name;
        this.age = age;
    }

    public void show(){
        System.out.println(name+"---"+age);
    }
}

一个标准类的3.0版本写法:
成员变量:被private修饰
构造方法:一个无参构造方法/一个带所有参数的构造方法
成员方法:getXxx()和setXxx(…)
show():打印所有成员变量的值
无论我们提供的是带参构造还是无参构造,只要是我们自己提供了一个,系统就永远不会提供了

class Teacher {
    private String name;
    private int age;

    //构造方法:
    Teacher() {

    }
    
    Teacher(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //getXxx()
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    //setXxx(...)
    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    //show()
    public void show() {
        System.out.println(name + "---" + age);
    }
}

public class TeacherDemo {
    public static void main(String[] args) {
        //使用无参构造方法创建对象,使用setXxx() 对成员变量进行赋值
        //开发使用这种方法
        Teacher t1 = new Teacher();
        t1.setName("小王");
        t1.setAge(18);
        t1.show();

        //使用带参数的构造方法创建对象并给成员变量进行赋值
      
        Teacher t2 = new Teacher("小杨", 18);
        t2.show();
    }
}

4、成员方法

根据返回值:
1、没有返回值。void 没有返回值的方法,直接调用可以输出结果
2、有返回值 有返回值的方法,调用的时候,需要用一个变量接收返回值或者直接使用
形式参数:
1、没有参数的方法
2、带参数的方法

class Function {
    //定义一个没有返回值没有参数的成员方法
    public void fun1() {
        System.out.println("这是一个没有返回值,没有参数的方法");
    }

    //定义一个没有返回值,带参数的方法
    public void fun2(String name) {
        System.out.println("这是带参数无返回值的方法:" + name);
    }

    //定义有返回值没有参数的方法
    public String fun3() {
        return "科技";
    }

    //定义一个有返回值有参数的方法
    public String fun4(String s) {
        return s + "你好";
    }
}
public class FunctionDemo {
    public static void main(String[] args) {
        //创建Function类的对象
        Function function = new Function();
        //没有返回值的方法,直接调用可以输出结果
        function.fun1();
        function.fun2("15期");

        //有返回值的方法,调用的时候,需要用一个变量接收返回值或者直接使用
        String s1 = function.fun3();
        System.out.println(s1);
        String s2 = function.fun4("小明");
        System.out.println(s2);
    }
}

5、类的初始化

内存图

在这里插入图片描述
在这里插入图片描述

Student s = new Student();在内存中做了哪些事情?

  • 加载Student.class文件进内存
  • 在栈内存为s开辟空间
  • 在堆内存为学生对象开辟空间
  • 对学生对象的成员变量进行默认初始化
  • 对学生对象的成员变量进行显示初始化
  • 通过构造方法对学生对象的成员变量赋值
  • 学生对象初始化完毕,把对象地址赋值给s变量

代码示例
定义一个长方形类,定义 求周长和面积的方法,然后定义一个测试了Test2,进行测试。

/*
定义一个长方形类,定义 求周长和面积的方法,然后定义一个测试了Test2,进行测试。
 */
class Rectangle1 {
    //定义成员变量
    private int length;
    private int width;

    //无参的构造方法
    public Rectangle1() {
    }

    //有参的构造方法
    public Rectangle1(int length, int width) {
        this.length = length;
        this.width = width;
    }
    //setXxx()和getXxx()

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    //定义成员方法,求周长    注意get时不需要传参数
    public int getGirth() {
        return 2 * (length + width);
    }

    //定义成员方法,求面积
    public int getArea() {
        return length * width;
    }

    //定义成员方法展示结果
    private void show() {
        System.out.println("长:" + length + ",宽:" + width);
    }
}
public class Rectangle {
    public static void main(String[] args) {
        //使用构造方法赋值
        Rectangle1 r1 = new Rectangle1(6, 5);
        int C = r1.getGirth();
        System.out.println("周长为:"+C);
        int S=r1.getArea();
        System.out.println("面积为:"+S);
    }
}

定义一个类MyMath,提供基本的加减乘除功能,然后进行测试

/*
定义一个类MyMath,提供基本的加减乘除功能,然后进行测试
 */
import java.util.Scanner;
class MyMath {
    //定义成员变量
    private int a;
    private int b;
    //无参的构造方法
    public MyMath() {
    }
    //有参的构造方法
    public MyMath(int a, int b) {
        this.a = a;
        this.b = b;
    }
    public int getA() {
        return a;
    }
    public void setA(int a) {
        this.a = a;
    }
    public int getB() {
        return b;
    }
    public void setB(int b) {
        this.b = b;
    }
    //定义成员方法显示a,b
    public void show() {
        System.out.println(a + "," + b);
    }
    //定义两数之和
    public int add() {
        return a + b;
    }
    //定义两数之差
    public int sub() {
        return a - b;
    }
    //定义两数之积
    public int mul() {
        return a * b;
    }
    //定义两数之差
    public double div() {
        return (a * 1.0) / b;
    }
}
public class MyMathDemo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入第一个操作数:");
        int num1 = sc.nextInt();
        System.out.println("请输入第二个操作数:");
        int num2 = sc.nextInt();
        MyMath MyMath = new MyMath(num1, num2);

        System.out.println("两数之和为" + MyMath.add());
        System.out.println("两数之差为" + MyMath.sub());
        System.out.println("两数之积为" + MyMath.mul());
        System.out.println("两数之商为" + MyMath.div());
    }
}

6、static关键字

static:静态的,可以修饰成员变量和成员方法
作用是可以让所有的对象共享一个成员变量
代码示例:

class Human {
    //姓名
    private String name;
    //年龄
    private int age;
    //国籍
//    private String country;
    private static String country;

    public Human() {
    }

    public Human(String name,int age){
        this.name = name;
        this.age = age;
    }

    public Human(String name, int age, String country) {
        this.name = name;
        this.age = age;
        this.country = country;
    }

    //getXxx()和setXxx(...)
    public void setCountry(String country) {
        Human.country = country;
    }

    public void show() {
        System.out.println("姓名:" + name + ",年龄:" + age + ",国籍:" + country);
    }
}
public class HumanDemo {
    public static void main(String[] args) {
        //创建第一个对象
        Human h1 = new Human("张杰", 42, "中国");
        h1.show();

        //创建第二个对象
        Human h2 = new Human("彭于晏", 38);
        h2.show();//中国

        //创建第三个对象
        Human h3 = new Human("蔡徐坤", 22);
        h3.show();//中国

        h3.setCountry("加拿大");
        h1.show();
        h2.show();
        h3.show();//都变成加拿大了
    }
}

static关键字的特点:
它可以修饰成员变量和成员方法
1、随着类的加载而加载(观察main方法)
2、优先于对象而存在的。
3、被类的所有对象共享:
举例:所有中国人的国籍信息都是中国都是一样。
什么时候使用静态static关键字呢?
如果某个成员变量是被所有的对象共享的,值是一样的,那么它就应该被定义为static静态的。
举例现实生活的案例:
哈罗共享单车(可以用静态的修饰)
自己的水杯(不可以用静态的修饰)
4、可以通过类名直接调用
一般情况下,只要我们看到一个类中有静态修饰的成员变量或者是成员方法
我们一律推荐使用 类名.静态成员 这种方式去使用
静态修饰的内容我们一般称之为:类成员,与类相关的。

static内存图
在这里插入图片描述
static关键字使用注意事项:
1、在静态方法中是没有this关键字的
this代表的是当前调用该方法的对象,而被static修饰的成员是优先于对象而存在的。
被static修饰的成员是随着类的加载而加载,这时候,还没有对象产生,也就说明没有this关键字
所以在静态方法中无法使用this关键字。
2、将成员方法分成两类:

            静态的成员方法:
                访问的内容:
                    成员变量:只能访问静态的成员变量
                    成员方法:只能访问静态的成员方法
            非静态的成员方法:
                访问的内容:
                    成员变量:既可以访问非静态的成员变量,也可以访问静态的成员变量
                    成员方法:既可以访问非静态的成员方法,也可以访问静态的成员方法

总结一句话:静态的只能访问静态的。

静态变量和成员变量的区别

所属不同

静态变量属于类,所以也称为为类变量
成员变量属于对象,所以也称为实例变量(对象变量)

内存中位置不同

静态变量存储于方法区的静态区
成员变量存储于堆内存

内存出现时间不同

静态变量随着类的加载而加载,随着类的消失而消失
成员变量随着对象的创建而存在,随着对象的消失而消失

调用不同

静态变量可以通过类名调用,也可以通过对象调用
成员变量只能通过对象名调用

7、代码块

在Java中,使用{}括起来的代码被称为代码块,根据其位置和声明的不同,
可以分为局部代码块,构造代码块,静态代码块,同步代码块(多线程中涉及)。

局部代码块:
在方法中出现,限定变量的生命周期,及早释放,提高内存的利用
在同一个类中的同一个方法中,如果存在多个局部代码块,执行顺序是自上而下的。
构造代码块:(在创建对象的时候调用)
定义在类中方法外。当一个类中既存在构造代码块也存在构造方法的时候,在创建对象时,会先执行构造代码块,后执行构造方法。
无论类中有多少个构造代码块,构造代码块之间会先进行自上而下的顺序执行,然后再执行构造方法。
构造代码块 – 构造方法
静态代码块:
在类中方法外定义,并加上static修饰。
静态代码块是优先于其他代码块之前执行,
静态代码块 – 局部代码块 – 构造代码块 – 构造方法
在加载的时候执行,并且只执行一次

public class CodeDemo {
    /**
     *  静态代码块
     */
    static {
        int a = 22;
        System.out.println(22);
    }

    CodeDemo(){
        int y = 300;
        System.out.println(y);
    }

    /**
     *      定义在类中方法外,使用大括号括起来的代码,称之为构造代码块
     */
    {
        int x = 200;
        System.out.println(x);
    }
    {
        int x = 400;
        System.out.println(x);
    }
    {
        int x = 500;
        System.out.println(x);
    }

    /**
     *  静态代码块
     */
    static {
        int a = 11;
        System.out.println(a);
    }

    public static void main(String[] args) {
        /**
         *  局部代码块
         */
        {
            int x = 10;
            System.out.println(x);
        }
//        System.out.println(x);
        {
            int y = 20;
            System.out.println(y);
        }
        {
            int z = 30;
            System.out.println(z);
        }

        CodeDemo codeDemo = new CodeDemo();
        CodeDemo codeDemo1 = new CodeDemo();
//        {
//            int z = 40;
//            System.out.println(z);
//        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值