第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
相关文章推荐
- 黑马程序员---java基础---面向对象中的构造方法及static关键字,变量的问题
- 面向对象_补充_封装_成员与局部变量_static关键字_Math随机数
- JAVA基础初探(三)面向对象思想、类与对象、成员变量与局部变量、构造方法、static关键字详解
- php学习笔记------[php面向对象中常用关键字与魔术方法]
- PHP面向对象之旅:parent::关键字
- (40)面向对象的三大特性继承性(41)面向对象中常用的关键字和魔术方法
- php 面向对象 this 关键字
- PHP面向对象中常用关键字和魔术方法
- java面向对象思想之方法的重载、this变量、静态变量、Java中的常量
- Java第二课 Java面向对象编程,面向对象编程和面向过程编程的区别,我们如何才能掌握面向对象的编程,类和对象的关系;讲解了Java中的构造、重载、this和super变量、静态变量、Java中的常
- 使用 final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
- 不用构造函数(Constructor)new关键字也能实现JavaScript的面向对象
- PHP面向对象之旅:static变量与方法
- 面向对象的开发5 抽象关键字abstract
- 面向对象高级(继承的基本实现、进一步研究、final关键字)
- JAVA面向对象基础:继承、变量隐藏、方法重写、包、修饰符、this、super
- JavaScript 面向对象程序设计 变量,函数定义之不可不知
- Javascript基础与面向对象基础~第二讲 Javascript中的变量及变量的类型
- java -- 面向对象概述及static关键字