JavaSE学习笔记(六)—— 面向对象 一、面向对象思想 二、类与对象的关系 三、对象内存图 四、成员变量和局部变量的区别 五、形式参数问题 六、匿名对象 七、封装 八、this关键字 九、构造方法 十、类的初始化过程 十一、面向对象练习 十二、static关键字 十三、代码块

1.1 面向对象思想引入

  前面我们讲过数组,当有多个数组都需要遍历时,我们可以将遍历的代码封装到方法中,需要遍历时,就调用相应的方法即可,提高代码的复用性。在对数组遍历的基础上继续增加需求,比如获取最值,数值逆序等,同样需要将这些功能封装到相应的方法中。这样继续封装会发现方法越来越多,于是就想能不能将这些方法继续进行封装呢?通过前面的讲解我们知道类是可以存放方法的,所以,我们就考虑使用类封装来这多个方法,将来再做数组的操作时,不用去找具体的方法,先找到这个类,然后使用这个类中的方法。这就是面向对象思想的编程方式。

1.2 面向过程思想概述

  我们来回想一下,之前我们完成一个需求的步骤:首先是搞清楚我们要做什么,然后在分析怎么做,最后我们再代码体现。一步一步去实现,而具体的每一步都需要我们去实现和操作。这些步骤相互调用和协作,完成我们的需求。
  在上面的每一个具体步骤中我们都是参与者,并且需要面对具体的每一个步骤和过程,这就是面向过程最直接的体现。
  那么什么是面向过程开发呢? 面向过程开发,其实就是面向着具体的每一个步骤和过程,把每一个步骤和过程完成,然后由这些功能方法相互调用,完成需求。
  面向过程的代表语言:C语言

1.3 面向对象思想概述

  当需求单一,或者简单时,我们一步一步去操作没问题,并且效率也挺高。可随着需求的更改,功能的增多,发现需要面对每一个步骤很麻烦了,这时就开始思索,能不能把这些步骤和功能在进行封装,封装时根据不同的功能,进行不同的封装,功能类似的封装在一起。这样结构就清晰了很多。用的时候,找到对应的类就可以了。这就是面向对象的思想。接下来我们看看面向对象到底是什么?

  面向对象是基于面向过程的编程思想。

面向过程:强调的是每一个功能的步骤
面向对象:强调的是对象,然后由对象去调用功能

1.4 面向对象的思想特点

  A:是一种更符合我们思想习惯的思想
  B:可以将复杂的事情简单化
  C:将我们从执行者变成了指挥者

【举例】
  买电脑:
    面向过程:我的了解电脑--了解我自己的需求--找对应的参数信息--去中关村买电脑--讨价还价--买回电脑
    面向对象:我知道我要买电脑 -- 班长去给我买 -- 班长就买回来了
  洗衣服:
    面向过程:把衣服脱下--找一个盆--放点洗衣粉--加点水--把衣服扔进去--搓一搓--清洗衣服--拧干--晾起来
    面向对象:把衣服脱下--打开全自动洗衣机--扔进去--一键即可--晾起来
  吃饭:
    面向过程:去超市买菜--摘菜--洗菜--切菜--炒菜--盛起来--吃
    面向对象:上饭店吃饭,你--服务员(点菜)--厨师(做菜)--服务员(端菜)--吃

1.5 面向过程和面向对象代码比较

  需求:把大象装进冰箱

【面向过程】

  动作有哪些呢?

    A:打开冰箱门
    B:装进大象
    C:关闭冰箱门

  代码体现;

class Demo {
    public static void main(String[] args) {
        /*
        System.out.println("打开冰箱门");
        //打开冰箱门的东西,我现在仅仅是为了演示,就写了一个输出语句
        //其实,它可能需要做很多操作。
        //这个时候代码就比较多一些了
        //假设我要多次打开冰箱门,
        //代码一多,每次都写一遍,麻烦不
        //我们就应该用方法改进
        
        System.out.println("装进大象");
        System.out.println("关闭冰箱门");
        */
        
        //写了方法以后,调用就改变了
        open();
        in();
        close();
    }
    
    public static void open() {
        System.out.println("打开冰箱门");
    }
    
    public static void in() {
        System.out.println("装进大象");
    }
    
    public static void close() {
        System.out.println("关闭冰箱门");
    }
}

【面向对象】

  我们怎么才能更符合面向对象思想呢?

    A:有哪些类呢?
    B:每个类有哪些东西呢?
    C:类与类直接的关系是什么呢?

  把大象装进冰箱的分析?

    A:有哪些类呢?

      大象
      冰箱
      Demo

    B:每个类有哪些东西呢?

      大象:
        进去
      冰箱:
        开门
        关门
      Demo:
      main方法
    C:类与类直接的关系是什么呢?
      Demo中使用大象和冰箱类的功能。

class 大象 {
    public static void in() {
        System.out.println("装进大象");
    }
}

class 冰箱 {
    public static void open() {
        System.out.println("打开冰箱门");
    }
    
    public static void close() {
        System.out.println("关闭冰箱门");
    }
}

class Demo {
    public static void main(String[] args) {
        冰箱调用开门
        大象调用进去
        冰箱调用关门
    }
}

1.6 面向对象开发、设计、特征

【面向对象开发】

  就是不断的创建对象,使用对象,指挥对象做事情。

【面向对象设计】

  其实就是在管理和维护对象之间的关系。

【面向对象特征】

  封装(encapsulation)
  继承(inheritance)
  多态(polymorphism)

二、类与对象的关系

  我们学习编程语言,就是为了模拟现实世界的事物,实现信息化。比如:去超市买东西的计费系统,去银行办业务的系统。
  我们如何表示一个现实世界事物呢:
    属性:该事物的描述信息
    行为:该事物能够做什么
  举例:学生事物

    姓名,年龄,性别...

    学习,吃饭,睡觉

  我们学习的Java语言最基本单位是类,所以,我们就应该把事物用一个类来体现。

  事物:       类:
    属性       成员变量
    行为          成员方法

  类:是一组相关的属性和行为的集合。是一个抽象的概念。

  对象:是该类事物的具体表现形式。具体存在的个体

  举例:
    学生:类
    班长:对象

  JavaSE学习笔记(六)—— 面向对象
一、面向对象思想
二、类与对象的关系
三、对象内存图
四、成员变量和局部变量的区别
五、形式参数问题
六、匿名对象
七、封装
八、this关键字
九、构造方法
十、类的初始化过程
十一、面向对象练习
十二、static关键字
十三、代码块

【类的定义】

  现实世界的事物:

属性    人的身高,体重等
行为    人可以学习,吃饭等

  Java中用class描述事物也是如此:

成员变量    就是事物的属性
成员方法    就是事物的行为

  定义类其实就是定义类的成员(成员变量和成员方法)

【如何创建对象呢】

  格式:类名 对象名 = new 类名();

【案例】

  定义一个学生类和学生测试类

/*    
    学生事物:
        属性:姓名,年龄,地址...
        行为:学习,吃饭,睡觉...
        
    把事物要转换为对应的类:
    
    学生类:
        成员变量:姓名,年龄,地址...
        成员方法:学习,吃饭,睡觉...
    
    首先我们应该定义一个类,然后完成类的成员。
   如何使用成员变量呢?对象名.变量名
  如何使用成员方法呢?对象名.方法名(...)
*/ //这是我的学生类 class Student { //定义变量 //姓名 String name; //年龄 int age; //地址 String address; //定义方法 //学习的方法 public void study() { System.out.println("学生爱学习"); } //吃饭的方法 public void eat() { System.out.println("学习饿了,要吃饭"); } //睡觉的方法 public void sleep() { System.out.println("学习累了,要睡觉"); } } //这是学生测试类 class StudentDemo { public static void main(String[] args) { //类名 对象名 = new 类名(); Student s = new Student(); //输出成员变量值 //System.out.println(s.name); //System.out.println(s.age); //System.out.println(s.address); //改进写法 System.out.println(s.name+"---"+s.age+"---"+s.address); //给成员变量赋值 s.name = "林青霞"; s.age = 27; s.address = "北京"; //赋值后的输出 System.out.println(s.name+"---"+s.age+"---"+s.address); //调用方法 s.study(); s.eat(); s.sleep(); } }

  定义一个手机类

/*
    手机事物:
        属性:品牌,价格,颜色...
        行为:打电话,发短信,玩游戏...
        
    手机类:
        成员变量:品牌,价格,颜色
        成员方法:打电话,发短信,玩游戏
*/
class Phone {
    //品牌
    String brand;
    //价格
    int price;
    //颜色
    String color;
    
    //打电话的方法
    public void call(String name) {
        System.out.println("给"+name+"打电话");
    }
    
    //发短信的方法
    public void sendMessage() {
        System.out.println("群发短信");
    }
    
    //玩游戏的方法
    public void playGame() {
        System.out.println("玩游戏");
    }
}

三、对象内存图

【一个对象的内存图】

JavaSE学习笔记(六)—— 面向对象
一、面向对象思想
二、类与对象的关系
三、对象内存图
四、成员变量和局部变量的区别
五、形式参数问题
六、匿名对象
七、封装
八、this关键字
九、构造方法
十、类的初始化过程
十一、面向对象练习
十二、static关键字
十三、代码块

【二个对象的内存图】

JavaSE学习笔记(六)—— 面向对象
一、面向对象思想
二、类与对象的关系
三、对象内存图
四、成员变量和局部变量的区别
五、形式参数问题
六、匿名对象
七、封装
八、this关键字
九、构造方法
十、类的初始化过程
十一、面向对象练习
十二、static关键字
十三、代码块

【三个对象的内存图】

JavaSE学习笔记(六)—— 面向对象
一、面向对象思想
二、类与对象的关系
三、对象内存图
四、成员变量和局部变量的区别
五、形式参数问题
六、匿名对象
七、封装
八、this关键字
九、构造方法
十、类的初始化过程
十一、面向对象练习
十二、static关键字
十三、代码块

四、成员变量和局部变量的区别

  1. 在类中的位置不同
    成员变量:在类中方法外
    局部变量:在方法定义中或者方法声明上
  2. 在内存中的位置不同
    成员变量:在堆内存
    局部变量:在栈内存
  3. 生命周期不同
    成员变量:随着对象的创建而存在,随着对象的消失而消失
    局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
  4. 初始化值不同
    成员变量:有默认初始化值
    局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。

【注意事项】

   局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则

class Varialbe {
    //成员变量
    //int num = 10;
    int num; //0
    
    public void show() {
        //int num2 = 20; //局部变量
        //可能尚未初始化变量num2
        //int num2; //没有默认值
        int num2 = 20;
        System.out.println(num2);
        
        //int num = 100;
        System.out.println(num);
    }
}

class VariableDemo {
    public static void main(String[] args) {
        Varialbe v = new Varialbe();
        
        System.out.println(v.num); //访问成员变量
        
        v.show();            
    }
}

五、形式参数问题

  • 基本类型:形式参数的改变不影响实际参数
  • 引用类型:形式参数的改变直接影响实际参数
//形式参数是基本类型
class Demo {
    public int sum(int a,int b) {
        return a + b;
    }
}

//形式参数是引用类型
class Student {
    public void show() {
        System.out.println("我爱学习");
    }
}

class StudentDemo {
    //如果你看到了一个方法的形式参数是一个类类型(引用类型),这里其实需要的是该类的对象。
    public void method(Student s) { //调用的时候,把main方法中的s的地址传递到了这里 Student s = new Student();
        s.show();
    }
}

class ArgsTest {
    public static void main(String[] args) {
        //形式参数是基本类型的调用
        Demo d = new Demo();
        int result = d.sum(10,20);
        System.out.println("result:"+result);
        System.out.println("--------------");
        
        //形式参数是引用类型的调用
        //需求:我要调用StudentDemo类中的method()方法
        StudentDemo sd = new StudentDemo();
        //创建学生对象
        Student s = new Student();
        sd.method(s); //把s的地址给到了这里
    }
}

六、匿名对象

  匿名对象:就是没有名字的对象。

【应用场景】

  1. 调用方法,仅仅只调用一次的时候。
    注意:调用多次的时候,不适合。因为每一次调用都会创建新的对象,浪费内存空间
  2. 匿名对象可以作为实际参数传递

【好处】

  匿名对象调用完毕就是垃圾。可以被垃圾回收器回收。

class Student {
    public void show() {
        System.out.println("我爱学习");
    }
}

class StudentDemo {
    public void method(Student s) {
        s.show();
    }
}

class NoNameDemo {
    public static void main(String[] args) {
        //带名字的调用
        Student s = new Student();
        s.show();
        s.show();//这里用的都是同一个对象
        System.out.println("--------------");
        
        //匿名对象
        //new Student();
        //匿名对象调用方法
        new Student().show();
        new Student().show(); //这里其实是重新创建了一个新的对象
        System.out.println("--------------");
        
        
        //匿名对象作为实际参数传递
        StudentDemo sd = new StudentDemo();
        //Student ss = new Student();
        //sd.method(ss); //这里的s是一个实际参数
        //匿名对象
        sd.method(new Student());
        
        //在来一个
        new StudentDemo().method(new Student());
     }
}

七、封装

  定义一个学生类:
    成员变量:name,age
    成员方法:show()方法

class Student {
    //姓名
    String name;
    //年龄
    private int age;
    
    //写一个方法对数据进行校验
    /*
        返回值类型:void
        参数列表:int a
    */
    public void setAge(int a) {
        if(a < 0 || age > 120) {
            System.out.println("你给的年龄有问题");
        }else {
            age = a;
        }
    }
    
    //show()方法,显示所有成员变量值
    public void show() {
        System.out.println("姓名:"+name);
        System.out.println("年龄:"+age);
    }
}

class StudentDemo {
    public static void main(String[] args) {
        //创建学生对象
        Student s = new Student();
        s.show();
        System.out.println("--------------");
        
        //给成员变量赋值
        s.name = "林青霞";
        //s.age = 27;
        s.setAge(27);
        s.show();
        System.out.println("--------------");
        
        //给age赋值
        //s.age = -27; //这个数据是不合理的
        //通过方法给值
        s.setAge(-27);
        s.show();
        System.out.println("--------------");
    }
}

  我们在使用这个案例的过程中,发现了一个问题:通过对象去给成员变量赋值,可以赋值一些非法的数据。这是不合理的。
  应该是这个样子的:在赋值之前,先对数据进行判断。判断到底在哪里做比较合适呢?StudentDemo类是一个测试类,测试类一般只创建对象,调用方法。 所以,这个判断应该定义在Student类中。
  而我们在成员变量的位置可不可以进行数据判断呢?是不可以的,因为做数据校验,必须要依靠一些逻辑语句。逻辑语句是应该定义在方法中的,所以,我们最终决定在Student类中提供一个方法来对数据进行校验。

  按照我们前面的分析,我们给出了一个方法进行校验。但是呢,它偏偏不调用方法来赋值,还是直接赋值了,这样我们的方法就没有起到作用。我就应该要求你必须使用我的方法,而不能直接调用成员变量赋值。怎么去强制要求不能直接使用成员变量呢?针对这种情况,Java就提供了一个关键字 private。

  其实我讲到现在讲解的是一个封装的思想。

7.1 封装概述

  封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。   

【好处】

  • 隐藏实现细节,提供公共的访问方式
  • 提高了代码的复用性
  • 提高安全性。

【封装原则】

  • 将不需要对外提供的内容都隐藏起来。
  • 把属性隐藏,提供公共方法对其访问。

7.2 private关键字

  • private一个权限修饰符
  • private可以修饰成员变量和成员方法
  • 被private修饰的成员只能在本类中被访问
class Demo {
    //int num = 10;
    //用private修饰
    private int num = 10;
    
    public void show() {
        System.out.println(num);
    }
    
    private void method() {
        System.out.println("method");
    }
    
    public void function() {
        method();
    }
}

class PrivateDemo {
    public static void main(String[] args) {
        Demo d = new Demo();
        //不能方法私有的成员变量
        //System.out.println(d.num);
        d.show();
        //不能访问私有的成员方法
        //d.method();
        d.function();
    }
}

【封装和private的应用】

  • 把成员变量用private修饰
  • 提供对应的getXxx()和setXxx()方法
//定义学生类
class Student {
    //姓名
    private String name;
    //年龄
    private int age;
    
    //姓名获取值
    public String getName() {
        return name;
    }
    
    //姓名设置值
    public void setName(String n) {
        name = n;
    }
    
    //年龄获取值
    public int getAge() {
        return age;
    }
    
    //年龄赋值
    public void setAge(int a) {
        age = a;
    }
}

//测试类
class StudentTest {
    public static void main(String[] args) {
        //创建学生对象
        Student s = new Student();
        
        //使用成员变量
        //错误:被私有修饰了,外界不能直接访问了
        //System.out.println(s.name+"---"+s.age);
        System.out.println(s.getName()+"---"+s.getAge());
        
        //给成员变量赋值
        //s.name = "林青霞";
        //s.age = 27;
        //通过方法给赋值
        s.setName("林青霞");
        s.setAge(27);
        System.out.println(s.getName()+"---"+s.getAge());
    }
}

八、this关键字

  拿上面的Student类作为例子:

//定义学生类
class Student {
    //姓名
    private String name;
    //年龄
    private int age;
    
    //姓名获取值
    public String getName() {
        return name;
    }
    
    //姓名设置值
    public void setName(String n) {
        name = n;
    }
    
    //年龄获取值
    public int getAge() {
        return age;
    }
    
    //年龄赋值
    public void setAge(int a) {
        age = a;
    }
}

  我们曾经说:起名字要做到见名知意。上面的setName(String n)和setAge(int a)显然不符合我们的命名规范,为了做到见明知意,应该定义为setName(String name)和setAge(int age),改进上面代码:

//定义学生类
class Student {
    //姓名
    private String name;
    //年龄
    private int age;
    
    //姓名获取值
    public String getName() {
        return name;
    }
    
    //姓名设置值
    public void setName(String name) { //name = "林青霞";
        name = name;
    }
    
    //年龄获取值
    public int getAge() {
        return age;
    }
    
    //年龄赋值
    public void setAge(int age) {
        age = age;
    }
}

//测试类
class StudentTest {
    public static void main(String[] args) {
        //创建学生对象
        Student s = new Student();
        
        //给成员变量赋值
        s.setName("林青霞");
        s.setAge(27);
        //获取数据
        System.out.println(s.getName()+"---"+s.getAge());
    }
}

  当我们在测试类中给Student赋值时,却发现获取不到我们所期望的值。这时因为变量的使用规则:就近原则。调用s.setName("林青霞")赋值的时候,setName()方法中的name变量其实是该方法内部的局部变量,给它赋值并不会影响Student类中成员变量name的结果,此时getName()得到的结果仍然是默认初始化值null。

  那我们是否可以这样写:

   //姓名设置值
    public void setName(String name) { //name = "林青霞";
        //name = name; //变量的使用规则:就近原则
        Student.name = name;//错误的
    }

  这里是类名,目前还没有说过类似的用法,所以这个是有问题的。这里的调用只能通过对象名,这个对象如果存在,它应该代表的是Student的一个对象。那么,谁能够代表当前类的对象呢? java就提供了一个关键字 this。

  this:是当前类的对象引用。简单的记,它就代表当前类的一个对象。哪个对象调用那个方法,this就代表那个对象

  将上述代码改进:

class Student {
    private String name;
    private int age;
    
    public String getName() {
        return name; //这里其实是隐含了this
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
}

class StudentTest2 {
    public static void main(String[] args) {
        //创建一个对象
        Student s1 = new Student();
        s1.setName("林青霞");
        s1.setAge(27);
        System.out.println(s1.getName()+"---"+s1.getAge());
        
        //创建第二个对象
        Student s2 = new Student();
        s2.setName("刘意");
        s2.setAge(30);
        System.out.println(s2.getName()+"---"+s2.getAge());
    }
}

对应的内存图为:

JavaSE学习笔记(六)—— 面向对象
一、面向对象思想
二、类与对象的关系
三、对象内存图
四、成员变量和局部变量的区别
五、形式参数问题
六、匿名对象
七、封装
八、this关键字
九、构造方法
十、类的初始化过程
十一、面向对象练习
十二、static关键字
十三、代码块

【this的应用场景】

  解决局部变量隐藏成员变量

九、构造方法

  构造方法:给对象的数据进行初始化。

【格式】

  • 方法名与类名相同
  • 没有返回值类型,连void都没有
  • 没有具体的返回值
class Student {
    private String name; //null
    private int age; //0
    
    public Student() {
        System.out.println("这是构造方法");
    }
}

class ConstructDemo {
    public static void main(String[] args) {
        //创建对象
        Student s = new Student();
        System.out.println(s); //Student@e5bbd6
    }
}

JavaSE学习笔记(六)—— 面向对象
一、面向对象思想
二、类与对象的关系
三、对象内存图
四、成员变量和局部变量的区别
五、形式参数问题
六、匿名对象
七、封装
八、this关键字
九、构造方法
十、类的初始化过程
十一、面向对象练习
十二、static关键字
十三、代码块

  我们一直在使用构造方法,但是,我们却没有定义构造方法,用的是哪里来的呢?

【构造方法的注意事项】

  • 如果我们没有给出构造方法,系统将自动提供一个无参构造方法。(可以通过反编译工具看出)
  • 如果我们给出了构造方法,系统将不再提供默认的无参构造方法。注意:这个时候,如果我们还想使用无参构造方法,就必须自己给出。建议永远自己给出无参构造方法
  • 构造方法也是可以重载的
class Student {
    private String name;
    private int age;

    public Student() {
        System.out.println("这是无参构造方法");
    }
    
    //构造方法的重载格式
    public Student(String name) {
        System.out.println("这是带一个String类型的构造方法");
        this.name = name;
    }
    
    public Student(int age) {
        System.out.println("这是带一个int类型的构造方法");
        this.age = age;
    }
    
    public Student(String name,int age) {
        System.out.println("这是一个带多个参数的构造方法");
        this.name = name;
        this.age = age;
    }
    
    public void show() {
        System.out.println(name+"---"+age);
    }
}

class ConstructDemo2 {
    public static void main(String[] args) {
        //创建对象
        Student s = new Student();
        s.show();
        System.out.println("-------------");
        
        //创建对象2
        Student s2 = new Student("林青霞");
        s2.show();
        System.out.println("-------------");
        
        //创建对象3
        Student s3 = new Student(27);
        s3.show();
        System.out.println("-------------");
        
        //创建对象4
        Student s4 = new Student("林青霞",27);
        s4.show();
    }
}

【注意】  

  A:给成员变量赋值有两种方式:setXxx()和构造方法,可以只写一种;

  B:如果不单独获取数据,可以不写getXxx()方法。

  学完构造方法后,以后再提类的组成:

  • 成员变量
  • 构造方法
  • 成员方法
    根据返回值:
        void类型
        非void类型
    形式参数:
        空参方法
        非空参方法

十、类的初始化过程

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

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

 JavaSE学习笔记(六)—— 面向对象
一、面向对象思想
二、类与对象的关系
三、对象内存图
四、成员变量和局部变量的区别
五、形式参数问题
六、匿名对象
七、封装
八、this关键字
九、构造方法
十、类的初始化过程
十一、面向对象练习
十二、static关键字
十三、代码块

十一、面向对象练习

  定义一个长方形类,定义 求周长和面积的方法,

/*
    长方形的类:
        成员变量:
            长,宽
        成员方法:
            求周长:(长+宽)*2;
            求面积:长*宽

*/

class ChangFangXing {
    //长方形的长
    private int length;
    //长方形的宽
    private int width;
    
    public ChangFangXing(){}
    
    //仅仅提供setXxx()即可
    public void setLength(int length) {
        this.length = length;
    }
    
    public void setWidth(int width) {
        this.width = width;
    }
    
    //求周长
    public int getZhouChang() {
        return (length + width) * 2;
    }
    
    //求面积
    public int getArea() {
        return length * width;
    }
}

class Test2 {
    public static void main(String[] args) {
        //创建键盘录入对象
        Scanner sc = new Scanner(System.in);
        
        System.out.println("请输入长方形的长:");
        int length = sc.nextInt();
        System.out.println("请输入长方形的宽:");
        int width = sc.nextInt();
        
        //创建对象
        ChangFangXing cfx = new ChangFangXing();
        //先给成员变量赋值
        cfx.setLength(length);
        cfx.setWidth(width);
        
        System.out.println("周长是:"+cfx.getZhouChang());
        System.out.println("面积是:"+cfx.getArea());
    }
}

  定义一个员工类,自己分析出几个成员,然后给出成员变量,构造方法,getXxx()/setXxx()方法,以及一个显示所有成员信息的方法。并测试。

/*
    分析:
        员工
            成员变量:
                员工编号,姓名,年龄
            构造方法:
                无参构造方法
            成员方法:
                getXxx()/setXxx()
                show();
*/
class Employee {
    //员工编号
    private String employeeId;
    //姓名
    private String name;
    //年龄
    private int age;
    
    //构造方法
    public Employee() {}
    
    //getXxx()/setXxx()
    public String getEmployeeId() {
        return employeeId;
    }
    
    public void setEmployeeId(String employeeId) {
        this.employeeId = employeeId;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
    
    //显示所有成员信息的方法
    public void show() {
        System.out.println("员工编号是:"+employeeId+"的这个人是:"+name+"的年龄是:"+age);
    }
}

class EmployeeTest {
    public static void main(String[] args) {
        //创建对象
        Employee e = new Employee();
        
        //给成员变量赋值
        e.setEmployeeId("czbk9527");
        e.setName("唐伯虎");
        e.setAge(18);
        
        //获取数据
        //System.out.println(e.getEmployeeId()+"---"+e.getName()+"---"+e.getAge());
    
        //我们在Employee类中定义了一个show方法。所以,我们改进一下,使用show方法
        e.show();
    }
}

十二、static关键字

  定义一个人类

class Person {
    //姓名
    String name;
    //年龄
    int age;
    //国籍
    //String country;
    static String country;
    
    public Person(){}
    
    public Person(String name,int age) {
        this.name = name;
        this.age = age;
    }
    
    public Person(String name,int age,String country) {
        this.name = name;
        this.age = age;
        this.country = country;
    }
    
    public void show() {
        System.out.println("姓名:"+name+",年龄:"+age+",国籍:"+country);
    }
}

class PersonDemo {
    public static void main(String[] args) {
        //创建对象1
        Person p1 = new Person("邓丽君",16,"中国");
        p1.show();
        
        //创建对象2
        //Person p2 = new Person("杨幂",22,"中国");
        //p2.show();
        Person p2 = new Person("杨幂",22);
        p2.show();
        
        //创建对象3
        //Person p3 = new Person("凤姐",20,"中国");
        //p3.show();
        Person p3 = new Person("凤姐",20);
        p3.show();
        
        p3.country = "美国";
        p3.show();
        
        p1.show();
        p2.show();
    }
}

  姓名和年龄都是变化的,这个我能接收,因为每个人的姓名和年龄是不同的。但是,我们现在选取的几个人都是中国人,他们的国籍是一样的。一样的国籍,我每次创建对象,在堆内存都要开辟这样的空间,我就觉得有点浪费了。怎么办呢?

  针对多个对象有共同的这样的成员变量值的时候,Java就提高了一个关键字来修饰:static。

【static的内存图解】——静态的内容存在于方法区的静态区

JavaSE学习笔记(六)—— 面向对象
一、面向对象思想
二、类与对象的关系
三、对象内存图
四、成员变量和局部变量的区别
五、形式参数问题
六、匿名对象
七、封装
八、this关键字
九、构造方法
十、类的初始化过程
十一、面向对象练习
十二、static关键字
十三、代码块

【static的特点】——(它可以修饰成员变量,还可以修饰成员方法)

  1. 随着类的加载而加载
    回想main方法,main方法是static修饰的,所以它随着类的加载而加载。想象一下,如果main方法在class文件加载后它还没有加载,那么jvm调用的时候就找不到它了
  2. 优先于对象存在
  3. 被类的所有对象共享
    举例:咱们班级的学生应该共用同一个班级编号。
    其实这个特点也是在告诉我们什么时候使用静态?
        如果某个成员变量是被所有对象共享的,那么它就应该定义为静态的。
    举例:
        饮水机(用静态修饰)
        水杯(不能用静态修饰)
  4. 可以通过类名调用
    其实它本身也可以通过对象名调用。
    推荐使用类名调用。

  静态修饰的内容一般我们称其为:与类相关的,类成员

【static关键字注意事项】

  1. 在静态方法中是没有this关键字的
    如何理解呢?
        静态是随着类的加载而加载,this是随着对象的创建而存在。
        静态比对象先存在。
  2. 静态方法只能访问静态的成员变量和静态的成员方法;非静态方法访问的成员变量,可以是静态的,也可以是非静态的,非静态方法访问的成员方法,可是是静态的成员方法,也可以是非静态的成员方法。简单记:静态只能访问静态
class Teacher {
    public int num = 10;
    public static int num2 = 20;
    
    public void show() {
        System.out.println(num); //隐含的告诉你访问的是成员变量
        System.out.println(this.num); //明确的告诉你访问的是成员变量
        System.out.println(num2);
        
        //function();
        //function2();
    }
    
    public static void method() {
        //无法从静态上下文中引用非静态 变量 num
        //System.out.println(num);
        System.out.println(num2);
        
        //无法从静态上下文中引用非静态 方法 function()
        //function();
        function2();
    }
    
    public void function() {
    
    }
    
    public static void function2() {
    
    }
}

class TeacherDemo {
    public static void main(String[] args) {
        //创建对象
        Teacher t = new Teacher();
        t.show();
        System.out.println("------------");
        t.method();
    }
}

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

  • 所属不同
    静态变量属于类,所以也称为为类变量
    成员变量属于对象,所以也称为实例变量(对象变量)
  • 内存中位置不同
    静态变量存储于方法区的静态区
    成员变量存储于堆内存
  • 内存出现时间不同
    静态变量随着类的加载而加载,随着类的消失而消失
    成员变量随着对象的创建而存在,随着对象的消失而消失
  • 调用不同
    静态变量可以通过类名调用,也可以通过对象调用
    成员变量只能通过对象名调用

【main方法讲解】

  public static void main(String[] args) {...}

  public:公共的,访问权限是最大的。由于main方法是被jvm调用,所以权限要够大。

  static:静态的,不需要创建对象,通过类名就可以。方便jvm的调用。
  void:因为我们曾经说过,方法的返回值是返回给调用者,而main方法是被jvm调用。你返回内容给jvm没有意义。
  main:是一个常见的方法入口。我见过的语言都是以main作为入口。
  String[] args:这是一个字符串数组。值去哪里了?
    这个东西到底有什么用啊?怎么给值啊?这个东西早期是为了接收键盘录入的数据的。格式是:java MainDemo hello world java

十三、代码块

  在Java中,使用{}括起来的代码被称为代码块。根据其位置和声明的不同,可以分为

  • 局部代码块:局部位置,用于限定变量的生命周期。
  • 构造代码块:在类中的成员位置,用{}括起来的代码。每次调用构造方法执行前,都会先执行构造代码块。
    作用:可以把多个构造方法中的共同代码放到一起,对对象进行初始化。

  • 静态代码块:在类中的成员位置,用{}括起来的代码,只不过它用static修饰了。
    作用:一般是对类进行初始化。

  静态代码块,构造代码块,构造方法的执行顺序?静态代码块 -- 构造代码块 -- 构造方法

  注意:静态代码块只执行一次;构造代码块每次调用构造方法都执行

class Code {
    //静态代码块
    static {
        int a = 1000;
        System.out.println(a);
    }

    //构造代码块
    {
        int x = 100;
        System.out.println(x);
    }
    
    //构造方法
    public Code(){
        System.out.println("code");
    }
    
    //构造方法
    public Code(int a){
        System.out.println("code");
    }
    
    //构造代码块
    {
        int y = 200;
        System.out.println(y);
    }
    
    //静态代码块
    static {
        int b = 2000;
        System.out.println(b);
    }
}

class CodeDemo {
    public static void main(String[] args) {
        //局部代码块
        {
            int x = 10;
            System.out.println(x);
        }
        //找不到符号
        //System.out.println(x);
        {
            int y = 20;
            System.out.println(y);
        }
        System.out.println("---------------");
        
        Code c = new Code();//1000  2000  100  200  code    
        System.out.println("---------------");
        Code c2 = new Code();//100  200  code
        System.out.println("---------------");
        Code c3 = new Code(1);//100  200  code
    }
}

  写程序的执行结果。

class Student {
    static {
        System.out.println("Student 静态代码块");
    }
    
    {
        System.out.println("Student 构造代码块");
    }
    
    public Student() {
        System.out.println("Student 构造方法");
    }
}

class StudentDemo {
    static {
        System.out.println("林青霞都60了,我很伤心");
    }
    
    public static void main(String[] args) {
        System.out.println("我是main方法");
        
        Student s1 = new Student();
        Student s2 = new Student();
    }
}

  JavaSE学习笔记(六)—— 面向对象
一、面向对象思想
二、类与对象的关系
三、对象内存图
四、成员变量和局部变量的区别
五、形式参数问题
六、匿名对象
七、封装
八、this关键字
九、构造方法
十、类的初始化过程
十一、面向对象练习
十二、static关键字
十三、代码块