值传递和引用传递的区别:class Demo { int x ; void show(Demo d) { d.x = 100; } void method( int y ) { int x = y+y; } } class Test { public static void main(String[] args) { Demo d = new Demo(); 这里是把Demo对象的引用传递给show方法,show方法会接收到Demo对象的引用,从而就可以根据引用来修改对象中的数据 d.show(d); System.out.println("d.x="+d.x); 这里是把对象空间中的成员变量x的值传递给了method方法,method方法中对x值做任何修改对原始值没有任何影响 d.method(d.x); System.out.println("d.x="+d.x); } } 值传递和引用传递的区别: 值传递相当于把原有的值复制了一份传递给了形参,那么形参拿到的是复制的值, 在形参所在的方法中对这个复制的值做任何改变,原始的值不会收到影响。 引用传递相当于把对象的引用复制一个传递给了形参,形参拿到的是对象的内存地址, 形参接收到这个地址之后,就可以去修改对象中的数据。 面向对象基本的特征:从今天开始我们要学习的任务是如何去书写一个类,以及在写这个类的时候类中能够书写什么,不能写什么,以及写的这些东西具体都是干什么的。 面向对象有三个基本的特征: 封装 继承 多态 1、封装:在前面学习方法的时候,我们说方法本身就是一个封装体,它中封装了具体的功能代码,当需要使用这个功能时,直接去调用即可。 后来我们把一些类似功能的方法又一次进行了封装,封装到了类中。也就是说类本身也是一个封装体。 生活中封装的举例: 电脑的硬件: CPU、内存、硬盘、主板、显卡、电源 把这些散件使用电线连接起来,就可以正常工作了。但是发现有一些弊端,开关机找不到,更重要的不安全。 由于不安全,就找一个六面板将这些硬件给组合在里面。但是这样的包装的之后那么带来的一些问题,在使用的时候,找到响应的 按钮了。这时就需要在板面上预留一些按钮和插口,方便外界来间接的去操作被封装起来的电脑硬件。 封装的体现: 在描述事物的时候,事物中不需要外界直接访问的内容,直接在事物中给封装起来,如果有部分内容需要外界来访问,在封装好之后,给外界暴漏出来一些接口或者按钮,那么让外界去通过这些按钮或者接口来间接的访问内部细节。 2、封装的好处封装的好处: 1、隐藏实现细节,同时可以保证安全。 2、把事物中不要暴漏出来的细节全部隐藏,然后对外提供访问内部细节的规则。 3、关键字private/* Person这个类本身就是一个封装体,其中封装了Person这类事物的属性和行为。 在Person类中有个age属性,当创建Person对象之后,就可以访问Person中的age成员变量, 这个age成员变量是int类型的。由于int类型的空间中可以存放正整数、零、负整数。 由于age是int类型,那么在代码的角度来考虑,是可以赋值负数的。、 我们就需要在编写程序的时候考虑如何去限制不让这个age成员变量为负数。 思考: 不让age为负数,那么就是不让外界访问到age,只要外界访问不到Person类中的 age成员变量,那么就无法给age赋值了。 当一个类中有些成员不需要当前类以外的地方访问到,Java给我们提供的解决方案: 就是把这个类中的成员使用私有关键字来修饰。 使用private关键字来修饰类中的成员,那么这个成员在这个类以外的地方就无法访问。 问题: 当把Person类中的age使用private关键字修饰之后,Person类以外的地方就访问不到了, 这样可以防止错误的数据,但是正确的数据也无法赋值进去。如何把正确的数据赋值给 age成员变量呢? 解决方案: 对外提供一个方法,让外界通过这个方法间接的访问到age。 总结: 日后在描述类的时候,类中不需要外界访问的成员都需要私有起来。 类中的成员变量,全部需要私有,并且对外提供setXxx方法和getXxx方法. private关键字有啥用? 当一个类中不需要外界访问的成员都需要使用private关键字来修饰。 private关键字可以修饰类中的成员。 可以修饰成员变量和成员方法。 被private修饰的成员,在本类以外地方无法访问。 */ class Person { private int age ; //对外提供一个专门用于给age设置值的方法 void setAge( int a ) { /* 在访问放到setAge方法之后,外界就会传递一个age的值进来, 当传递一个年龄的值进来之后,首先不要把传递进来的值直接赋值 给age成员变量,先对这值做合法性的判断,只有这个值正确了, 才赋值成员变量age */ if( a < 0 || a > 150 ) { //判断成立后,说明传递进来的这个年龄是非法的,就不能赋值给age成员变量 return ; //throw new RuntimeException("对不起,传递进来的年龄非法!!!"); } age = a; } //对外提供获取年龄值的方法 int getAge() { return age; } void say() { System.out.println("age="+age); } } class PersonDemo { public static void main(String[] args) { Person p = new Person(); //p.age = -22; //调用Person中用于给成员变量age赋值的setAge方法 p.setAge(-22); p.say(); } } 构造方法1、构造方法定义格式构造方法: 在前面学习的过程中,创建的Person对象,它们的成员变量都是默认的值。 而在真实生活中,很多情况下一有这个对象,那么就会有它的属性值, 在创建对象的过程中,这个对象就有自己的属性值。 要子在创建对象的过程中就明确对象的基本属性值,那么就需要使用Java中给我们提供 的构造方法这个技术来完成。 构造方法的定义: 构造方法其实就是在构建和创造对象的过程中要执行的方法。 定义格式: 1、方法名必须和类名一致。 2、构造方法没有返回值。也不能书写void 构造方法格式: 修饰符 类名( 参数 ) { } 一般方法的定义格式: 修饰符 返回值类型 方法名(参数) { } 注意: 构造方法是没有返回值类型的,如果在类中书写一个方法,方法名和类名相同, 但这个方法书写了返回值类型,那么当前这个方法就不是构造方法,它仅仅是当前这个类中的 一个普通方法。 在开发时普通方法的名称不要和类型一致。 2、构造方法的执行过程class PersonDemo2 { public static void main(String[] args) { Person p = new Person("华安",27); p.say(); Person p2 = new Person("秋香",18); p2.say(); } } main方法首先执行,在main方法中创建Person对象。在堆中就会给当前Person对象分配内存空间,当把内存空间分配好之后,开始给堆中当前这个对象的成员变量进行默认的初始化值。成员变量默认初始化完成之后,开始调用与之对应的构造方法。对应的构造方法开始接收创建对象时传递的数据,当把这些数据接收完成之后,开始执行构造方法中的代码。当构造方法中的代码执行完成之后,构造方法出栈,这时才代表当前这个对象创建完成,在把对象的内存地址赋值给p这个引用变量。 3、构造方法调用细节思考: 当类中的成员变量被私有了,需要对外提供get和set方法。 当类中已经有构造方法,可以给成员变量赋值,那么还有必要提供get和set方法吗? 构造方法是在对象创建的过程中成员变量被默认初始化完成之后,就被调用了。 当构造方法执行完成之后,对象才彻底创建完成。也就是说在对象创建完成之后构造方法已经执行完。 即便是在一个类中有构造方法可以给对象成员变量进行赋值,也需要get和set方法。 思考: 1、构造方法能不能调用一般的方法 在构造方法中是可以调用一般方法的。 构造方法的作用是在创建对象的时候给指定的对象进行初始化的。 在构造方法执行的时候,已经有对象了,并且这个对象的成员变量已经默认初始化完成。 2、一般的方法能不能调用构造方法 在一般方法中不允许调用构造方法。 一般方法需要在对象已经存在的情况由对象去调用。既然对象已经存在,说明构造方法已经执行完成了。 构造方法我们不能手动的去调用,而是在创建对象的时候,由对象自己去调用。 4、构造方法之间调用思考: 在一个类中能不能有多个构造方法? 在一个类中是可以有多个构造方法的,多个构造方法是以重载的形式存在。 不同的构造方法它们主要是给不同的对象进行初始化的。 注意: 在一个类中如果没有手动的添加构造方法,那么在这个类中会有个默认的空参数的构造方法。 如果在这个类中我们手动的书写了构造方法,那么这个无参数的默认构造方法就没有了。 在真实开发中,如果这个类在创建对象的时候,要求必须明确一些数据值,那么在这个类中就不要书写 无参数的构造方法。 这样做的目的就是防止外界创建无参数的对象。 Person( String nm ) { name = nm; } //这个构造方法只能给年龄和姓名赋值 Person( String nm ,int a ) { name = nm; age = a; } 在Person( String nm )这个构造方法中可以给name赋值,那么在Person( String nm ,int a ) 构造方法中就不要再出现重复的代码了。 可以在Person( String nm ,int a )这个构造方法中去调用Person( String nm )构造方法。 当我们在同一个类中要调用本类的其他构造方法,不能通过构造方法的名称去掉哟个, 需要使用this关键字来调用。 this调用构造方法的格式: this(实参); 5、构造方法之间调用细节构造方法之间相互调用的时候,一定要注意不能形成递归调用。 在一个类中有多个构造方法时,它们之间可以使用this(参数)形式调用,最后有一个构造方法中是没有的。 this调用本类的其他构造方法时,this的调用必须放在当前这个构造方法中的第一行。 初始化的动作必须最先执行。 6、成员变量和局部变量同名问题当在一个类中如果成员变量和局部变量同名的时候,如果要在这个局部范围内去 访问类中的成员变量,需要使用this关键字来区分。 格式: this.成员名 在Java中如果要去访问一个变量,那么会现在自己所属的区域中查找有没有这个变量, 如果没有才会去成员位置继续查找。找到就可以执行,如果没有报错。 在使用this调用类中的其他成员时,在调用的地方会有一个隐式的this, 这个this用来表示当前到底是那个对象调用的自己,那个对象调用自己,this就指向那个对象。 谁调用自己,this就指向谁。 7、this练习:需求:描述人,在人中拥有一个比较是否是同龄人的功能 静态关键字1、静态关键字介绍2、静态修饰成员方法 |
|