面向对象
OOP object Oriented Programming(万物皆对象)
面向过程
定义:分析解决问题所需要的步骤,然后用函数来一步一步的调用实现。
例:将大象放入冰箱 ①打开冰箱 ②将大象放入冰箱 ③关闭冰箱
面向对象
定义:抽取一类具有相同属性和行为的事物
例:冰箱:打开门、关上门; 大象:走路;
面向对象关注的是哪些事物有什么样的功能,强调的是具体的事物。
类
定义:我们把某些具有相同属性和行为(对象的方法)
的事物抽象成一类。它类似一个模板,对象(实例)
是根据此模板产生的样本。类是一个概念,是抽象的。但对象(实例)是具体的。
语法:
class 类名 {
cladd A{
属性;
//属性(成员变量)的语法,初始值可有可无
数据类型 属性名 = 初始值;
int age = 0;
//无初始值
数据类型 属性名;
String name;
//根据类创建对象
//类名相当于数据类型
类名 对象名 = 类名();
A a = a();
//给一个具体的对象的属性赋值
对象名.属性名 = 值/变量;
a.age = 10;
//调用类的对象的方法,括号类可以有参数
对象名.方法名();
//此时调用的为无返回值的example方法
a.example();
行为;
//行为(对象的方法)的语法
public 返回值类型(或为void) 方法名 (数据类型 参数名...){
方法体;
//当返回值类型为void时无return语句
return 数据;
}
//例:
public int example(){
System.out.println("Example1");
return 1;
}
public void example(int a){
System.out.println("Example2");
}
}
对象间的互相赋值
首先是根据同一个类对象化出来对象a、对象b,再将已经赋过值的对象a,赋给未赋值的对象b后,(语法:类名 对象b = 对象a;
)改变了对象b任一属性的值,那么相对应对象a中同一属性的值也会发生同样的变化。
原理:在内存中,对象及其值存储在堆中,对象的地址存储在栈中。将对象a值赋给对象b时,对象b直接指向存储在栈中对象a的地址,而不是在栈中重新开辟一块内存空间来存储对象b的地址。
局部变量、成员变量
局部变量 | 成员变量(类的属性) |
---|---|
在方法或语句块中定义 | 在当前类的大括号内定义 |
必须赋初始值方可使用 | 可以不赋初始值,但有默认初始值 |
在内存中,局部变量存储在栈中 | 在内存中,成员变量存储在堆中 |
生命周期短(定义时产生,在当前方法括号内语句块的括号执行完毕就会消失) | 随着对象的消失而消失,最终被jvm的垃圾回收器回收 |
回收语法:System.gc();
匿名对象(无主对象)
匿名对象由于没有栈中的变量引用,所以就会被回收掉,匿名对象是无意义的。
封装
定义:将属性私有化,以至于这种属性只有本类才能访问(使用private关键字)
。我们一般对每一个私有属性提供公共public
的set和get这种方法供外界来访问私有属性。
目的:提高数据安全性,通过封装可以实现对属性的访问权限控制,同时增加了程序的可维护性。
如果在其他类中直接访问一个带有private的属性时会报错。
set方法
控制改变属性值的权限;get方法
控制访问属性值的权限。
步骤:①在当前封装属性的类中创建set/get方法(get方法有返回值)。
②在主方法中进行调用,从而实现传值和访问。
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
//this后的name是属性,等号后及括号内的name是参数
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
this关键字
当直接打印输出一个对象时,将会输出一个由jdk提供的地址。
this只能在类的对象方法中使用
有this的一定是属性,没有this的一定是方法的参数名
this代表当前调用这个this所在的方法的对象的自身
解释:首先,在对象方法中this关键字被正确使用,当主方法中已被创建出的对象A调用这个对象方法,那么这个对象方法中的this就是指对象A。
this可以在方法内区分同名的成员变量和局部变量
解释:在方法中当类的属性
(成员变量)和参数
(局部变量)同名时可以使用this区分。(详见上面的封装)
this. 变量名(访问成员变量)
this. 方法名(调用成员方法)
class Student{
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//这里访问name和age其实有隐藏地使用this
//System.out.println("我的名字是:"+this.name+" "+"我的年龄是:"+this.age);
public void introduce() {
System.out.println("我的名字是:"+name+" "+"我的年龄是:"+age);
}
}
public class TestStudent {
public static void main(String[] args) {
//创建Student对象
Student student = new Student();
//给封装的name、age赋值
student.setAge(20);
student.setName("张三");
//调用introduce方法
student.introduce();
}
}
内存中解析:
①java编译器(javac.exe)编译出TestStudent.class、、Student.class字节码文件,java解释器(java.exe)将TestStudent.class文件载入到jvm中并将其中的所有方法(main方法)存储在静态方法区内。
②java解释器继续将main方法压入栈内存来执行main方法。
③jvm在堆中创建Student对象时,jvm会将Student.class文件载入到jvm中(首先将方法存储到静态方法区内,而属性属于成员变量,只有在时(new)才会在堆中产生)
,然后将introduce、getAge、setAge、getName、setName方法存储到静态方法区,其次在堆中创建Student对象并开辟一块内存空间存储其属性(带有初始值),在栈中创建student变量,将再把堆中Student对象的内存地址
存储在student变量中。
④student调用setAge方法,jvm将setAge方法压栈,将带有参数的student变量的地址赋给调用setAge的this,然后通过this给堆中Student对象的age属性赋值,setAge方法执行完毕并出栈。
⑤调用setName方法(过程与④同理)。
⑥student调用introduce方法,jvm将introduce方法压栈并执行该方法,然后通过this(详见代码中的注释)获取到name和age属性的值,并执行输出语句,执行完毕后introduce方法出栈。
⑦main中全部方法执行完毕后,main方法出栈,student变量消失。
⑧由于Student对象失去了引用,成为了匿名对象,所以被回收。
构造器
作用:创建对象,给对象的属性赋初始值。构造器本身是一个方法。
语法:
//有参构造器
private 类名 (数据类型 参数名,...){
方法体;
}
public 类名 (数据类型 参数名,...){
方法体;
}
//默认无参构造器,在类中隐式存在
public 类名(){
}
package com.GouZaoQi;
class Student{
//Student的成员属性age和name
int age;
String name;
char gender;
//创建无参构造器
public Student(){
//无参构造器直接赋值
this.name = "赵一";
}
//创建有参构造器(只有一个参数)
public Student(String name) {
//接收到创建对象时传递进来的值,并使用this将值赋给成员属性
this.name = name;
}
//这里使用了重载
// 创建有参构造器(含有两个参数)
//接收到创建对象时传递进来的值,将值赋给成员属性
public Student(String name,int age) {
//这里的this代表调用了只含有一个参数的构造器
this(name);
//接收到创建对象时传递进来的值,并使用this将值赋给成员属性
this.age = age;
}
//这里使用了重载
// 创建有参构造器(含有三个参数)
public Student(String name,int age,char gender) {
//这里的this代表调用了含有两个参数的构造器
this(name,age);
//接收到创建对象时传递进来的值,并使用this将值赋给成员属性
this.gender = gender;
}
public void introduce() {
System.out.println("我的名字是:"+name+" "+"我的年龄是:"+age + "我的性别是:"+gender);
}
}
public class TestStudent {
public static void main(String[] args) {
Student student = new Student();//使用无参构造器
//含有有参构造器实例化对象时,可在括号内直接传入参数
Student student1 = new Student("张三");//使用只有一个参数的构造器
Student student2 = new Student("李四",20);//使用有两个参数的构造器
Student student3 = new Student("王五",40,'男');//使用有三个参数的构造器
student.introduce();//结果 我的名字是:赵一 我的年龄是:0我的性别是:
student1.introduce();//结果 我的名字是:张三 我的年龄是:0我的性别是:
student2.introduce();//结果 我的名字是:李四 我的年龄是:20我的性别是:
student3.introduce();//结果 我的名字是:王五 我的年龄是:40我的性别是:男
}
}
注意:
①构造器没有返回值,没有void;
②构造器的方法名必须和类名一致
③在构造器中可以使用this(...)
调用其它的构造器,但this(...)
语句必须放在构造器方法的第一行,详见代码注释
④在类中隐式存在着一个默认无参的构造器,当类中定义了一个有参构造器时,默认无参的构造器将被覆盖并不可使用,如果此时想要使用默认无参构造器时,只需将其显示定义出来即可。
⑤构造方法是可以被private修饰的,作用:在其他类中无法创建该类的对象