面向对象
对象
java中流传一句“万物皆对象!”,对象是描述现实事物的具体体现。一辆车是一个对象,一个人是一个对象,编程的最终目的是将现实事物用代码的形式表现出来。对象是类实例化的产物。
//实例化,car就是一个对象
Car car = new Car();
类
是一类对象将其共性内容抽取出来放到一起包装起来,是抽象的事物。共性内容包括:属性(成员变量)和行为(成员方法)。比如:人类是一个类,其对象有男有女国籍不同等。动物也是一个类。抽象可以理解为:动物这个类中,可以走动,可以吃东西,但是具体是哪种动物吃的什么不知道。
//同一个源文件只能存在一个public修饰的类
//表示Car类
class Car{
}
对象和类的关系
对象是显示事物实实在在的个体,是看得到摸得着的事物
- 类是一类相同对象抽取共性得到的抽象事物,是创建对象的模板,类具有属性和行为
- 对象的创建可以看成是通过类这个模板加上自己特有的属性行为刻画出来的。比如动物会叫,具体到猫:喵喵叫,狗:汪汪汪
- 使用对象时需要先进行实例化,再进行赋值和调用方法
构造方法
- 构造方法的格式是:权限修饰符 类名(参数列表){…方法体…}。构造方法没有返回值,连void也不能出现。如果出现就是普通的方法,而不是构造方法!!构造方法是一个类中必不可少的代码片段。创建一个类必须要定义构造方法。实际上我们实例化一个对象,就是调用类的构造方法初始化创建一个了一个具体的对象。
我们看到下面代码Car类中没有主动声明构造方法当依然能正确,是因为系统会默认隐式的创建一个空参数的构造方法。
class car(){
//属性
String color;
String name;
double price;
//行为
public void run(){
System.out.println();
}
}
public class TestA(){
public static void main (String[] agrs){
//Car类实例化对象,实际是调用Car()这个构造方法进行对象的初始化
Car car1 = new Car();
car1.color = "五菱宏光";
car2.name = "五彩斑斓的黑色";
car1.price = 10000;
car1.run;
}
}
- 我们也可以手动定义构造方法,但是注意,如果我们手动定义了构造方法,那么系统就不会再默认给我们创建无参构造方法。所以一般我们都会手动定义无参跟有参的构造方法
- 构造方法的作用是:对实例化的对象进行初始化,有参数的构造方法可以使就简化代码的编写·。不需要重复调用对象.属性来赋值。只需要在实例化过程中传入实参即可,实现了局部变量为全局变量赋值。
public Car(String name,String color,double price){
..........
}
main(){
//调用的是有参的构造方法实例化对象car2,简化了一个个属性的赋值
Car car2() = new Car("五菱宏光","五彩斑斓的黑色",10000);
//此时我们调用空参构造方法实例化对象会报错
//Car car1 = new Car();
}
构造方法总结与注意事项
1. 构造方法的格式:权限修饰符 类名(参数类型 形式参数1,参数类型 形式参数2,…){…方法体}
2. 构造方法必须与类名相同,且不能有返回值,连void都不能有
3. 一个类实例化对象实际上是调用构造方法创建对象,所以类必须要有构造方法存在
4. 如果没有定义构造方法,JVM会隐式创建空参构造方法,如果定义了构造方法,JVM就不会自动创建空参构造方法。所以我们创建一个类,一般都会手动创建构造方法
5. 构造方法的作用:实现局部变量传递给成员变量。简化属性定义的赋值操作。
this关键字解析
- this关键字实际是对象的代指,哪个对象调用它就代表哪个对象,代指当前对象。
- 一般用在属性和构造方法中。用在属性上,是为了区分传入参数(局部变量)和成员变量重名的情况。this的变量代表本类的成员变量。如下面代码,Car类中成员变量和局部变量重名,this关键字可以将局部变量赋值给属性。值得注意的是:在java中,值得传递是就近原则的,如果没有this标记,那么相当于自己传值给自己,是没有意义的
- this用在构造方法上代表引用指向本类的构造方法。值得注意的是一个构造方法中只能定义一个this()构造方法,且必须在第一行第一个被执行如下代码,Car类定义多个重载的构造方法,可以通过this构造方法简化构造函数的定义
//1.定义一个Car类
public class Car {
//1.1) 定义类的属性(成员变量)
public String prand;
public String color;
public double price;
public int wheels;
//1.2)定义空参构造方法
public Car() {
}
//1.3)定义两个参数的构造方法
public Car(String prand, String color) {
//如果没有this修饰,那么会出现自己赋值给自己的情况,这是无意义的
//prand= prand;
this.prand = prand;
this.color = color;
}
//1.4) 定义四个参数的构造方法
public Car(String prand, String color, double price, int wheels) {
this(prand,color);
//简化了下面两个的赋值定义
//this.prand = prand;
//this.color = color;
this.price = price;
this.wheels = wheels;
}
//1.5) 定义Car类的行为(成员变量)
public void run(){
System.out.println(this.color + this.prand + "发动了!");
}
}
this总结
1. this关键字指向的是当前对象的引用
2. this.属性:为了解决局部变量和成员变量重名的问题,this可以使局部变量赋值给成员变量
3. this([参数列表]):这里的this代表当前构造出来的那个对象,代表调用本类的其他构造方法。必须放在第一行且只能有一个在一个构造方法内存在一个this调用的构造方法。这样做大大简化了构造方法的定义,提高代码的重用性
toString方法的重写
- 所有类都继承了Object中的toString方法,该方法打印的是对象的地址值。所以为了满足我们对打印对象具体信息的需求,一般根据自己需求重写toString方法
- 重写:子类与父类具有相同的方法,包括方法名和参数列表。父类的方法的具体实现不是子类需要的,这时就可以通过重写override来实现子类方法的具体实现细节
- 直接打印对象实际上是调用tostring的方法,如下代码:
//1.6) 重写toString方法
@Override
public String toString() {
return "品牌:" + this.prand +
"\n颜色:" + this.color +
"\n价格:" + this.price +
"\n车轮:" + this.wheels;
}
//打印对象,实际上是调用toString()方法
System.out.println(car1);
equals 和 == 比较的区别
- = =比较:用在基本数据类型中即为直接比较两个数是否相等,用在比较对象时候实际上是比较两个对象的地址值。我们知道,我们通过new一个对象,即是他们的属性方法完全相同,但肯定不是同一个对象。比如我们new了两辆车,即使他们一模一样,也不是同一辆。用在String中,string的变量会先到池中寻找是否有相同值,如果有那么直接指向这个值,那么即使是两个不同的str1和str2,返回的也是true
package com.laiwei.test;
public class test01 {
public static void main(String[] args) {
//1.==比较基本数据类型
int a = 1;
int b = 1;
System.out.println(a == b); //true
//2. ==比较String类型
String str1 = "123";
String str2 = "123";
String str3 = str2;
System.out.println(str1 == str2); //true
System.out.println(str3 == str2); //true
//3. ==比较对象
Car car1 = new Car();
Car car2 = new Car();
System.out.println(car1); //Car@1b6d3586
System.out.println(car2); //Car@4554617c
System.out.println(car1 == car2); //false,底层实现是判断两个地址值是否相等
}
}
- equals比较:比较的是具体的值。这个方法比较的只能是对象而不能是基本数据类型。当比较的对象时,其底层实现依然是= =的比较,这是因为我们写类时不可能知道对象的具体实现细节以及属性都有什么,所以我们一般会重写Object中equals的方法来实现值的比较
//4. equals比较对象
System.out.println(car1.equals(car2)); //false,因为其底层源码实际就是==的判断
/*
Object中实现的方法
public boolean equals(Object obj) {
return (this == obj);
}
*/
@Override
public boolean equals(Object obj) {
return this.prand.equals(prand)
&& this.color.equals(color)
&& this.price == price
&& this.wheels == wheels;
}
//3.比较car1和car2的属性是否相等
System.out.println(car1.equals(car2));// true
System.out.println(car1 == car2); //false