第9章:面向对象变量与关键字

成员变量与局部变量

成员变量和局部变量的区别?
1.在类中的位置不同

  • 成员变量:在类中方法外
  • 局部变量:在方法定义中或者方法声明上。

2.在内存中的位置不同

  • 成员变量: 在堆内存
  • 局部变量: 在栈内存

3.生命周期不同
* 成员变量:随着对象的创建而存在,随着对象的消失而消失
* 局部变量:随着方法的调用而存在,随着方法的调用完毕而消失。

4.初始化值不同
* 成员变量:有默认初始化值
* 局部变量:没有默认初始化值,必须定义,赋值,然后才能使用

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

/*
    成员变量和局部变量的区别?
    A:在类中的位置不同
        成员变量:在类中方法外
        局部变量:在方法定义中或者方法声明上。
 */
class Variable
{
    //成员变量
    //int num = 10;
    int num;//

    public void show()
    {
        //int num2 = 20;//局部变量
        //int num1;//没有默认值
        int num1 = 10;
        System.out.println(num1);

        //int num = 100;
        System.out.println(num);
    }
}
public class VariableDemo {
    public static void main(String[] args)
    {
        Variable v = new Variable();
        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();
    }
}

public class ArgsTest {
    public static void main(String[] args)
    {
        //形式参数是基本类型的调用
        Demo d = new Demo();
        int result = d.sum(10,20);
        System.out.println("result = "+result);

        //形式参数是引用类型的调用
        //需求:我要调用StudentDemo类中的method()方法
        StudentDemo sd = new StudentDemo();
        //创建学生对象
        Student s = new Student();
        sd.method(s);//把s的地址给到了这里
    }
}

匿名对象

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

  • 是对象的一种简化表示形式

匿名对象的两种使用情况

  • 对象调用方法仅仅一次的时候
    注意:
    调用多次的时候不适合。那么,这种匿名调用有什么好处吗?
    有,匿名对象调用完毕后就是垃圾。 可以被垃圾回收器回收。
  • 作为实际参数传递
class Student {
    public void show()
    {
        System.out.println("我爱学习");
    }
}
class StudentDemo{
    public void method(Student s)
    {
        s.show();
    }
}
public 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();//这里其实是重新创建了一个新的对象


        //匿名对象作为实际参数传递
        StudentDemo sd = new StudentDemo();
        //Student ss = new Student();
        //sd.method(ss);//这里的ss是一个实际参数
        //sd.method(new Student());//

        //匿名对象
        sd.method(new Student());


        //再来一个
        new StudentDemo().method(new Student());


    }

}

封装概述

我们在使用这个案例的过程中,发现了一个问题
通过对象去给成员赋值,可以赋值一些非法的数据
这是不合理的

应该是这个样子的:在赋值之前,先对数据进行判断
判断到底在哪里做比较合适呢?
Student类是一个测试类,测试类一般指创建对象,调用方法。

所以,这个判断应该定义在Student1类中
而我们在成员变量的位置,可不可以进行判断呢?
逻辑语句是应该定义在方法中的,所以,我们最终决定在Student类中
提供一个方法来对数据进行校验
按照我们前面的分析,我们给出了一个方法进行校验
但是呢,她偏偏不调用方法来赋值,还是直接赋值了
这样我们的方法就没有起到作用。
我就应该要求你必须使用我的方法,而不能直接调用成员变量赋值
怎么去强制要求不能直接使用成员变量呢?
针对这种情况java就提供了关键字private
private:私有的,可以修饰成员变量和成员方法

/*
    定义一个学生类:
    成员变量:name,age
    成员方法:show()方法
 */
class Student1{
    //姓名
    String name;
    //年龄
    int age;


    //写一个方法对数据进行校验
    /*
     * 返回值类型: void
     * 参数列表:int age
     */
    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);
    }


}


public class Student {
    public static void main(String[] args)
    {
        //创建学生对象
        Student1 s = new Student1();
        s.show();

        System.out.println("----------");

        //给成员变量赋值
        s.name="罗巍";
        s.age = 23;
        s.show();
        System.out.println("----------");

        //给age赋值
        s.SetAge(-27);//这个数据是不合理的
        s.show();
        System.out.println("----------");




    }
}

注意:被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();
    }

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

private的标准用例

private最常见的应用

  • 把成员变量用private修饰
  • 提供对应的getXxx()setXxx()方法

作业

请把手机类写成一个标准类,然后创建对象测试功能

手机类:成员变量:
品牌:String brand;
价格:int price;
颜色:String color;
成员方法:
针对每一个成员变量给出对应getXXX()/setXxx()方法。
最后定义测试:
创建一个对象,先通过getXxx()方法输出成员变量的值。这一次的结果是:null—0—null
然后通过setXxx()方法给成员变量赋值。再次输出结果。这一次的结果是:三星—2999—土豪金

class phone{
    //品牌
    private String brand;
    //价格
    private int price;
    //颜色
    private String color;

    //Get()和Set()方法
    public String getBrand()
    {
        return brand;
    }
    public void setBrand(String brand)
    {
        this.brand = brand;
    }
    public int getPrice()
    {
        return price;
    }
    public void setPrice(int price){
        this.price = price;
    }
    public String getColor()
    {
        return color;
    }
    public void setColor(String color)
    {
        this.color = color;
    }

}
public class PhoneTest {
    public static void main(String[] args)
    {
        phone s = new phone();
        System.out.println(s.getBrand()+"---"+s.getPrice()+"---"+s.getColor());

        phone s1 = new phone();
        s1.setBrand("三星");
        s1.setPrice(2999);
        s1.setColor("土豪金");
        System.out.println(s1.getBrand()+"---"+s1.getPrice()+"---"+s1.getColor());


    }
}

构造方法

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

格式:
A:方法名与类名相同
B : 没有返回值类型,连void都没有
C :没有具体的返回值

class Student{
    private String name;//null
    private int age;//0
    public Student()//这就是构造方法
    {
        System.out.println("这是构造方法");
    }
}
public class ConstructDemo {
    public static void main(String[] args)
    {
        //创建对象
        Student s = new Student();
        System.out.println(s);
    }

}

构造方法的重载及注意事项

构造方法的注意事项:

  • 如果我们没有给出构造方法,系统将自动提供一个无参构造方法
  • 如果我们给出了构造方法,系统将不再提供一个默认的无参构造方法。
    注意:这个时候如果我们还想使用无参数构造的方法,就必须自己给出。建议永远自己给出无参构造方法。
class Student1{
    private String name;
    private int age;

    public Student1()  //构造方法必须要与类名相同
    {
        System.out.println("这是无参构造方法");
    }

    //构造方法的重载格式
    public Student1(String name)
    {
        System.out.println("这是带一个String类型的构造方法");
        this.name = name;

    }
    public Student1(int age)
    {
        System.out.println("这是带一个int类型的构造方法");
        this.age = age;
    }
    public Student1(String name,int age)
    {
        System.out.println("这是一个带多个参数的构造方法");
        this.name = name;
        this.age = age;
    }

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

    }

}
public class ConstructDemo2 {
    public static void main(String[] argsw)
    {
        //创建对象
        Student1 s = new Student1();
        s.show();
        System.out.println("--------");

        //创建另一个对象
        Student1 s2 = new Student1("林青霞");
        s2.show();
        System.out.println("--------");

        //创建对象3
        Student1 s3 = new Student1(19);
        s3.show();
        System.out.println("--------");

        //创建对象4
        Student1 s4 = new Student1("林青霞",12);
        s4.show();
        System.out.println("--------");

    }
}

由上可知:
给成员变量赋值有两种方式
1. setXxx()方法
2. 构造 方法

一个基本类的标准代码写法

//一个标准代码的最终版
//学生类:
//成员变量:NAME,AGE
//构造方法:无参,带两个参数
//成员方法:GETXXX()/SETXXX()
//      SHOW();输出该类的所有成员变量值
//给成员变量赋值的方式有两种:
//A:setXxx()方法
//B:构造方法
//输出成员变量的方式
//A:通过getXxx()分别获取然后拼接,一般都是靠拼接做的
//B:通过show()方法
class Student3{
    //姓名
    private String name;
    //年龄
    private int age;

    //构造方法
    public Student3(){

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

    }
    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(name+"--"+age);
    }
}   
public class StudentDemo {
    public static void main(String[] args)
    {
        //方式1给成员变量赋值
        //无参构造方法+setXxx()
        Student3 s1 = new Student3();
        s1.setName("罗巍");
        s1.setAge(90);
        //输出值
        System.out.println(s1.getName()+"--"+s1.getAge());
        s1.show();


        //方式2给成员变量赋值
        Student3 s2 = new Student3("罗巍",23);
        System.out.println(s2.getName()+"--"+s2.getAge());
        s2.show();
    }

}

面向对象练习

练习1 定义一个类Demo,其中定义一个求两个数据和的方法,定义一个测试了Test,进行测试。



class Demo{


//  private int a;
//  private int b;
//  
//  //创建构造方法
//  public Demo(int a ,int b){
//      this.a = a;
//      this.b = b;
//  }
//  public int sum(int a ,int b)
//  {
//      return a+b;
//  }
//  public void show()
//  {
//      System.out.println("sum = "+(a+b));
//  }

//  虽然这种方法可以,并且好像是符合了面向对象的思想,但是不好
//  因为我们曾经说过:类是一组相关的属性和行为的集合,并且是通过食物转换过来的
//  而类中的成员变量就是食物的属性,属性是用来描述事物的
//  同理:成员变量其实就是用来描述类的

    public int sum(int a ,int b)
    {
        return a+b;
    }


}
public class Test {
    public static void main(String[] args)
    {
        //创建对象
        Demo s = new Demo();
//      s.show();

        System.out.println(s.sum(4,5));
    }
}

因此:
变量什么时候定义维成变量:
如果这个变量是用来描述这个类的信息的,那么,该变量就应该定义为成员变量。

变量到底定义在大范围好还是小范围好:
变量的范围是越小越好,因为能被及时的被回收。

练习2 定义一个长方形类,求周长和面积的方法,然后定义一个测试类Test,进行测试。

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

注意:import 必须出现在所有类型的前面


import java.util.*;  //import必须出现在所有类的前面

class ChangFangXing{
    //长方形的长
    private int length;
    //长方形的高
    private int width;

    public ChangFangXing(){ }

//  public int getLength()
//  {
//      return length;
//  }

    //仅提供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;
    }


//  PUBLIC VOID CANDS(INT CHANG,INT KUAN){
//      INT S = CHANG*KUAN;
//      INT C = (CHANG+KUAN)*2;
//  }

}


public class Squretest {
    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 s = new ChangFangXing();
        s.setLength(length);
        s.setWidth(width);

        System.out.println("周长是:"+s.getZhouchang());
        System.out.println("面积是:"+s.getArea());

    }
}

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

分析:
员工

* 成员变量:员工编号、姓名、年龄
* 构造方法:无参构造方法
* 成员方法:getXxx()/setXxx();show()
import java.util.Scanner;

class empo{
    private String name;
    private int age;
    private String gender;
    private String work;

    //构造方法
    public empo(){}

    //获取name
    public String GetName()
    {
        return name;
    }

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

    //age
    public int getAge(){
        return age;
    }

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

    //gender
    public String getGender()
    {
        return gender;
    }
    public void setGender(String gender)
    {
        this.gender = gender;
    }

    //work
    public String getWork()
    {
        return work;
    }
    public void setWork(String work)
    {
        this.work = work;
    }

    public void show()
    {
        System.out.println("员工信息:姓名 "+name+" 年龄 "+age+" 性别 "+ gender+"工作"+work);
    }

}
public class test {
    public  static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入员工的姓名");
        String name = sc.nextLine();
        System.out.println("请输入员工的年龄");
        int age = Integer.parseInt(sc.nextLine());
        System.out.println("请输入员工的性别");
        String gender = sc.nextLine();
        System.out.println("请输入员工的工作");
        String work = sc.nextLine();


        empo s = new empo();
        s.setName(name);
        s.setAge(age);
        s.setGender(gender);
        s.setWork(work);
        s.show();
    }
}

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

import java.util.Scanner;

class MyMath{
    //成员变量
    private int a;
    private int b;

    //构造方法
    public MyMath(){    
    }

    //加法
    public void getAdd(){
        System.out.println("两者的相加结果为a+b = "+(a+b));

    }
    public void setNum(int a, int b)
    {
        this.a = a;
        this.b = b;
    }

    //减法
    public void getSub(){
        System.out.println("两者的相减结果为a-b = "+(a-b));
    }

    //乘法
    public void getMul(){
        System.out.println("两者的相乘结果为a*b = "+(a*b));
    }

    //除法
    public void getDiv(){
        System.out.println("两者的相除结果为a/b = "+(a/b));
    }

}
public class test2 {
    public static void main(String[] args)
    {
        Scanner s1  = new Scanner(System.in);
        System.out.println("请输入第一个数字");
        int a = s1.nextInt();
        System.out.println("请输入第二个数字");
        int b = s1.nextInt();
        //创建对象
        MyMath s = new MyMath();
        s.setNum(a, b);
        s.getAdd();
        s.getDiv();
        s.getMul();
        s.getSub();


    }

}

static 关键字的引入

class Person{
    //姓名
    String name;
    //年龄
    int age;
    //国籍
    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);
    }
}
public class PersonDemo {
    public static void main(String[] args){
        //创建对象
        Person p1  = new Person("罗巍",18,"中国");
        p1.show();
        //创建对象2 
        Person p2 = new Person("杨幂",22,"中国");
        p2.show();
        //创建对象3
        Person p3 = new Person("凤姐",20,"中国");
        p2.show();
    }
}

姓名和年龄都是变化的,这个我能接受,因为每个人的姓名和年龄是不同的
但是我们现在选取的人都是中国人,他们的国籍是一样的
一样的国籍,我每次创建对象,再堆内存都要开辟这样的空间
我就觉得有点浪费了:怎么办呢?针对多个对象有共同的成员变量值的时候,
java提供了一个关键字来修饰:static

static的特点

它可以修饰成员变量,还可以修饰成员方法
* 随着类的加载而加载(回想main方法)
* 优先于对象存在
* 被所有对象共享 举例:我们班的学生应该公用同一个班级编号。其实这个特点也是再告诉我们什么时候使用静态。如果某个成员变量是被所有对象共享的,那么他就应该定义为静态的。
* 可以通过类名调用 其实它本身也可以通过对象名调用。
推荐使用类名调用静态修饰的内容一般我们称其为:与类相关的,类成员

class Student{
    //非静态变量
    int num = 10;

    //静态变量
    static int num2 = 20;

}
public class StudentDemo {
    public static void main(String[] args)
    {
        Student s = new Student();
        System.out.println(s.num);


        System.out.println(Student.num2);
        System.out.println(s.num2);

    }
}

static关键字的注意事项

  1. 在静态方法中是没有this关键字的
    如何理解呢:
    应为静态是随着类的加载而加载,this是随着对象的创建而存在。镜像比对象先存在。
  2. 静态方法只能访问静态的成员变量和静态的成员方法

    • 静态方法:
      成员变量:只能访问静态变量
      成员方法:只能访问静态成员方法
    • 非静态方法:
      成员变量:可以是静态的,也可以是非静态的。
      成员方法:可以是静态的成员方法,也可以是非静态的成员方方法。

简单记:
静态只能访问静态

main方法是静态的

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值