------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
面向对象
2.1了解面向对象
2.1.2 面向对象的概念
面向对象是相对面向过程而言,面向对象和面向过程都是一种思想。面向过程强调的是每一个功能的步骤,代表语言:C语言。面向对象强调的是对象,然后由对象去调用功能,代表语言:Java、C++、C#。
例子:把大象装进冰箱。用面向过程实现:1. 打开冰箱。2.
存储大象。3. 关上冰箱。"打开"、"存储"、"关上"都是功能行为,在代码中的直观体现就是函数或者方法,这就是一种面向过程的以功能行为为主体的思想体现。用面向对象实现:1. 冰箱打开。2.
冰箱存储。3. 冰箱关闭。可以看到,所有的操作都是以"冰箱"为主体,而不是功能行为。也就是说冰箱自己已经具备"打开"、"存储"、"关上"的行为功能,我们只需要让冰箱执行它具备的功能就可以了。这就是一种面向对象的以执行功能的对象为主体的思想体现。
2.1.2
面向对象的特点
是一种符合人们思考习惯的思想,可以将复杂的事情简单化,将程序员从执行者转换成了指挥者。
完成需求时:
1. 先要去找具有所需功能的对象来用。
2. 如果该对象不存在,那么创建一个具有所需功能的对象。
2.1.3
面向对象开发,设计,特征
开发的过程:其实就是不断的创建对象,使用对象,指挥对象做事情。
设计的过程:其实就是在管理和维护对象之间的关系。
面向对象的特征:
封装(encapsulation)
继承(inheritance)
多态(polymorphism)
2.2类与面向对象
使用计算机语言就是不断地在描述现实生活中的事物。Java中描述事物通过类的形式体现,类是具体事物的抽象,概念上的定义。 对象即是该类事物实实在在存在的个体。
2.2.1
类与对象(图例)
可以理解为:类就是图纸,汽车就是堆内存中的对象。 对于同一类事物可以抽取它们的共性的内容,定义在类中。如:生活中的汽车,每一台车都有轮胎数和颜色。那么在通过java描述汽车这类事物时,就可以将这两个共性属性作为类中的属性进行定义。通过该类建立的每一个汽车实体都具有该属性,并可以有对象特有的属性值。
2.2.2 类的定义
生活中描述事物无非就是描述事物的属性和行为。如:人有身高,体重等属性,有说话,打球等行为。Java中用类class来描述事物也是如此。
属性:对应类中的成员变量。
行为:对应类中的成员函数。
定义类其实在定义类中的成员(成员变量和成员函数)。
2.2.3创建对象、使用对象
创建对象:类名 对象名 = new 类名();
使用成员变量:对象名.成员变量
使用成员方法:对象名.成员方法
示例:
class Phone{ //品牌 String brand; //价格 int price; //颜色 String color; //打电话的方法 public void call(String name){ System.out.println("给"+name+"打电话"); } //发短信方法 public void sedMessage(){ System.out.println("发短息"); } } class PhoneDemo{ public static void main(String[] args){ //创建手机对象 Phone p = new Phone(); //直接输出成员变量的值 System.out.println(p.brand+"---"+p.price+"---"+p.color); //给成员变量赋值 p.brand = "一加"; p.price = 1999; p.color = "black"; //再次输出 System.out.println(p.brand+"---"+p.price+"---"+p.color); //调用方法 p.call("classmate"); p.sedMessage(); } }
运行结果:
2.2.4 对象的内存结构
示例:
Car c1 = new Car();
c1.color="blue";
Car c2 = new Car();
只要是用new操作符定义的实体就会在堆内存中开辟一个新的空间,并且每一个对象中都有一份属于自己的属性。
通过对象.对象成员的方式操作对象中的成员,对其中一个对象的成员进行了修改,和另一个对象没有任何关系。
需要提到的是c1、c2都是对实体的引用变量,如果执行c2 = c1,那么c2也就指向了c1引用的实体。c2原来引用的实体因为没有被引用变量引用,就会被垃圾回收器回收。
2.2.5 成员变量和局部变量
1、在类中的位置不同:
成员变量:在类中方法外
局部变量:在方法定义中或者方法声明上
2、在内存中的位置不同
成员变量:在堆内存
局部变量:在栈内存
3、生命周期不同
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
4、初始化值不同
成员变量:因为在堆内存中,所以有默认初始化值
局部变量:因为在栈内存中,没有默认初始化值,必须定义,赋值,然后才能使用。
注意事项:
局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。
示例:
class Variable{ int num;//成员变量,默认初始化值为0 public void show(){ int num = 2;//局部变量 System.out.println(num); int num2 = 1;//局部变量 System.out.println(num2); } } class VariableDemo{ public static void main(String[] args){ Variable v = new Variable(); System.out.println(v.num);//访问成员变量 v.show(); } }
运行结果:
2.2.6 基本数据类型参数及引用数据类型参数传递
示例1:基本数据类型参数传递
//基本数据类型参数传递 class Demo { public static void main(String[] args){ int x = 3; show(x); System.out.println("x=" + x); } public static void show(int x){ x = 4; } }
运行结果:
执行过程说明:
1、jvm调用main方法,main方法入栈。
2、将x变量值设置为3。
3、main方法调用show方法,3作为基本数据类型参数赋值给show方法参数x,也就是说,此时show方法的参数x值为3。
4、show方法执行x=4后,show方法的参数x值变为4。
5、show方法执行结束,show方法出栈。show方法参数x也随之出栈。
6、main方法打印x的值。此时x指的是main方法中的x变量的值(show方法中的参数x已经随show方法一块出栈了)。所以,打印出来的x值为3而不是4。
7、main方法执行结束,出栈。
示例2:引用数据类型参数传递
//引用数据类型参数传递 class Demo { int x = 3; public static void main(String[] args){ Demo d = new Demo(); d.x = 9; show(d); System.out.println(d.x); } public static void show(Demo d){ d.x = 4; } }
运行结果:
执行过程分析:
1、jvm调用main方法,main方法入栈。
2、创建Demo对象d(在堆内存中创建,d作为引用变量,指向堆内存中创建的实体对象),并将d指向的实体对象中的属性x的值设置为9。
3、main方法调用show方法,d作为引用数据类型参数赋值给show方法参数d,也就是说,此时show方法的参数d和main方法中的变量d同时指向了堆内存中同一个实体对象。
4、show方法执行d.x=4后,堆内存中的实体对象的x属性值变为4。
5、show方法执行结束,show方法出栈,show方法参数d也随之出栈。虽然show方法参数d出栈了,但是,由于main方法的变量d依然引用着堆内存中的实体对象,因此堆内存中的实体对象不会被垃圾回收器清除。
6、main方法打印d.x的值。此时,d指的是main方法中的引用变量x,d.x指的依然是堆内存中的实体对象中x的值。所以,打印出来的值为4而不是9。
7、main方法执行结束,出栈。
总结:
在java中,方法参数的传递永远都是传值,而这个值,对于基本数据类型,值就是你赋给变量的那个值。而对于引用数据类型,这个值是对象的引用(一个地址值),而不是这个对象本身。
2.2.7 匿名对象
匿名对象:匿名对象是对象的简化形式。
匿名对象两种使用情况:
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(); System.out.println("--------------"); //建立一个匿名对象 new Student(); //匿名对象调用方法 new Student().show(); System.out.println("--------------"); //匿名对象作为实际参数传递 StudentDemo sd = new StudentDemo(); //匿名对象的使用 sd.method(new Student()); //匿名对象的使用 new StudentDemo().method(new Student()); } }
运行结果:
2.3封装
2.3.1了解封装
概述:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处:
隐藏实现细节,提供公共的访问方式
提高了代码的复用性
提高安全性
封装原则:
将不需要对外提供的内容都隐藏起来
把属性隐藏,提供公共方法对其访问
2.3.2 private
private是一种权限修饰符,用于修饰类中的成员变量和成员方法,私有只有在本类中有效。例如下面的例子,将类Student里变量age和name私有化以后,在类Student以外即使建立了该类的对象也不能直接访问,但是学生应该有age和name这两个属性,所以就在Student中提供对应访问age和name的方式。
class Student{ private String name; private int age; //年龄的获取 public int getAge(){ return age; } //年龄的赋值 public void setAge(int a){ age = a; } //姓名的获取 public String getName(){ return name; } //姓名的赋值 public void setName(String n){ name = n; } } //测试类 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=classmate; name是Student类的私有成员,外部无法直接对其赋值 //s.age=22; age是Student类的私有成员,外部无法直接对其赋值 //通过方法给成员变量赋值 s.setName("classmate"); s.setAge(22); System.out.println(s.getName()+"---"+s.getAge()); } }
运行结果:
注意事项:private只是封装的一种体现。类、方法也是封装的体现。
2.4 构造方法
2.4.1 怎么判断一个函数是否是构造方法?
1、方法名与类名相同
2、没有定义返回值类型
3、没有返回值,但是可以简单的写上return;
构造方法的作用:给对象初始化。因为对象一建立就会调用与之对应的构造方法,所以构造方法可以用于给对象进行初始化。
class Student { private String name; //null private int age; //0 public Student() { System.out.println("这是构造方法"); } public void speak(){ System.out.println("name:"+name+",age:"+age); } } class ConstructDemo { public static void main(String[] args) { //创建对象 Student s = new Student(); System.out.println(s); //[email protected] s.speak(); } }
运行结果:
注意:
1、当类中没有定义构造方法时,系统会默认给该类加入一个空参数的构造方法。
2、当类中自定义了构造方法后,系统便不会再建立默认的构造方法了。这个时候,如果我们还想使用无参构造方法,就必须自己给出。
2.5 this关键字
2.5.1 this的介绍
代表它所在方法所属对象的引用,也就是说哪个对象在调用this所在的方法,this就代表哪个对象。
2.5.2 this的应用
1、当定义类中功能时,该方法内部要用到调用该方法的对象时,这是用this来表示这个对象。
2、当局部变量和成员变量同名时,可以用this来区分。
3、可以使用this语句调用本类当中的构造函数,但是this语句只能定义在构造函数的第一行,因为初始化时要先执行。
class Person{ private String name; private int age; private Person(){ } private Person(String name){ this();//this语句只能定义在构造函数的第一行,因为初始化时要先执行。 this.name = name;//用this区分后,前面的name就是成员变量,后面的name就是局部变量。 } Person(String name,int age){ //this.name = name; this(name);//this语句只能定义在构造函数的第一行,因为初始化时要先执行。 this.age = age; System.out.println("name:"+ name +",age:"+ age); } } class PersonDemo4{ public static void main(String [] args){ Person p = new Person("lisi",30); } }
运行结果:
2.6 static关键字
static是一个修饰符,用于修饰成员(成员变量,成员函数);当成员被静态修饰后,就多了一种调用方式,除了可以被对象调用外,还可以直接被类名调用。写法格式:类名.静态成员
2.6.1 被static修饰后的成员的特点:
1、随着类的加载而加载,随着类的消失而消失。也就是说它的生命周期最长。
2、优先于对象存在。
3、被所有对象共享。
4、可以直接被类名调用。
class Person{ String name;//成员变量,也叫实例变量。 static String country = "CN";//静态的成员变量,也叫类变量。 public void show(){ System.out.println(name+"::"+country); } } class StaticDemo{ public static void main(String [] args){ Person p = new Person(); p.name = "zhangsan"; p.show(); System.out.println(p.country);//被对象调用 System.out.println(Person.country);//被类调用 } }
运行结果:
2.6.2 成员变量(实例变量)和静态变量(类变量)的区别
1、 别名不同
成员变量也称为实例变量;静态变量也称为类变量。
2、生命周期不同
成员变量随着对象的创建而存在,随着对象被回收而释放。
静态变量随着类的加载而存在,随着类的消失而消失。
3、调用方式不同
成员变量只能被对象调用;静态变量可以被对象调用,还可以被类名调用。
4、 数据存储位置不同
成员变量存储在堆内存的对象中,所以也叫对象的特有数据。
静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。
注意事项:
1、静态方法中不可以定义this,super关键字。
静态是随着类的加载而加载,this是随着对象的创建而存在。上有一静态比对象先存在。
2、静态方法只能访问静态成员(静态方法和静态变量)。
非静态方法既可以访问静态也可以访问非静态。
class Person{ String name; static String country = "CN"; //静态方法 public static void show(){ System.out.println(country + ":" + name); } }
编译时会报错:
2.6.3 主函数
主函数是静态的,是一个特殊的函数,作为程序的入口,可以被JVM调用。
主函数的定义:
public:代表该函数访问权限是最大的。
static:不需要对象调用,直接用主函数所属类名调用即可。 命令行窗口中输入:java StaticDemo,实际上就是在执行StaticDemo.main();。
void:因为我们曾经说过,方法的返回值是返回给调用者,而main方法是被jvm调用。返回内容给jvm没有意义。
main:main不是关键字,但是是一个特殊的单词,可以被JVM识别。
String[] args:这是主函数的参数列表,是一个数组类型的参数,而且元素都是字符串类型。
2.7 创建对象做了哪些事情
创建一个对象时都做了哪些事情呢? 例如:Student s = new Student("zhangsan",20);
1、把Student.class文件加载到内存。
2、在栈内存为s开辟空间。
3、在堆内存为学生对象申请空间。
4、给学生的成员变量进行默认初始化(int类型的变量默认值为0,double类型的变量默认值为0.0,String类型的变量默认值为null)。
5、给学生的成员变量进行显示初始化(int age = 10;)。
6、通过构造方法给成员变量进行初始化。
7、对象构造完毕,把地址赋值给s变量。
2. 8面向对象练习题
1、什么时候将变量定义为成员变量呢?
需求1:定义一个类Demo,其中定义一个求两个数据和的方法,然后定义一个测试了Test,进行测试。
import java.util.Scanner; class Demo{ public int sum(int a,int b){ return a+b; } } class Test{ public static void main(String[] args){ //创建键盘录入对象 Scanner sc = new Scanner(System.in); System.out.println("请输入第一个数:"); int a = sc.nextInt(); System.out.println("请输入第二个数:"); int b = sc.nextInt(); //创建对象 Demo d = new Demo(); System.out.println("两数之和为:"+d.sum(a,b)); } }
运行结果:
需求2:定义一个长方形类,定义 求周长和面积的方法,然后定义一个测试了Test2,进行测试。
<span style="font-size:18px;">import java.util.Scanner; class Rectangle{ private int length;//定义成员变量长 private int width;//定义成员变量宽 public void setLength(int length){ this.length = length; } public void setWidth(int width){ this.width = width; } //获取周长 public int getPerimeter(){ return 2*(length + width); } //获取面积 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(); //创建对象 Rectangle r = new Rectangle(); //对长进行赋值 r.setLength(length); //对宽进行赋值 r.setWidth(width); System.out.println("长方形的周长:"+r.getPerimeter()); System.out.println("长方形的面积:"+r.getArea()); } }</span>
运行结果:
那么什么时候应该将变量定义为成员变量呢?我们知道,类是一组相关的属性和行为的集合,并且类是通过事物转换过来的,而类中的成员变量就是事物的属性,属性是用来描述事物的,所以成员变量就是用来描述类的。因此,如果这个变量是用来描述这个类的信息的,那么,该变量就应该定义为成员变量。在需求1中,数据a和数据b并不能描述类Demo,所以不应该将a、b定义为Demo类的成员变量。在需求2中,长length和宽width是长方形的属性,是用来描述长方形的,所以应该将其定义为成员变量。
版权声明:本文为博主原创文章,未经博主允许不得转载。