您的位置:首页 > 其它

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

2016-09-12 19:59 351 查看

成员变量与局部变量

成员变量和局部变量的区别?

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;
}
}
//形式参数是引用
4000
类型
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关键字的注意事项

在静态方法中是没有this关键字的

如何理解呢:

应为静态是随着类的加载而加载,this是随着对象的创建而存在。镜像比对象先存在。

静态方法只能访问静态的成员变量和静态的成员方法



静态方法:

成员变量:只能访问静态变量

成员方法:只能访问静态成员方法

非静态方法:

成员变量:可以是静态的,也可以是非静态的。

成员方法:可以是静态的成员方法,也可以是非静态的成员方方法。

简单记:

静态只能访问静态

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐