一、 面向对象编程
1 我们如何在京东购买手机
京东商城是我们大家所熟知的电商平台。在平台首页导航中包含了平台商品的全部分类。京东为了更好的管理好这些商品,都会不同类型的商品都在程序中创建出自己对应的分类。通过通过分类也可以让网站浏览器更容易的找到自己想要购买的商品。
每个分类下面又有具体的商品。例如:点击导航中手机可以看见很多手机,虽然都是手机,但是因为厂家、型号等不同,对应不同的手机。
当我们进入到手机详情页面中时,选择好版本、颜色等就买到具体型号、具体配置的手机了。
我们虽然在网站上购买了手机,并已经付款了,但是这些操作都是在京东商城这款软件中操作的,然后京东工作人员(目前已经自动化了)会根据网站中用户选择的具体商品,从仓库中进行发货,通过物流把真实商品快递到用户手中。这一套流程都是从虚拟到现实的一套流程,这也是我们说的:软件是为了解决现实生活问题的,用户可以通过京东,足不出户的买到自己的产品,给广大消费者提供了极大便利。
2 柯南三步走
难道说(《名侦探柯南》)。
问题一:
京东商城是如何能够让用户在数以亿计的商品中找到自己想要的产品的?
答:用户可以在搜索栏中搜索自己想要商品的信息。也可以通过分类找到自己想要商品的所属分类。
问题二:
用户是如何在分类结果或搜索结果下,找到自己想要的手机的?
答:可以通过品牌、CPU型号、颜色、内存大小、店铺名称等参数来选择自己的商品。
问题三:
我们如何知道自己最后购买的商品就是自己想要买的商品?
答:只要品牌、内存大小、型号等匹配对了,就是我们想要购买的商品。
如果我的推理没错的话(《名侦探柯南》)
京东商城中每个商品都有自己所属分类,而每个分类下的商品根据参数的不同又对应不同的商品。
真相只有一个(《名侦探柯南》)
京东商城是使用Java语言编写的。这种把软件中内容和现实生活内容一一对应的编程方式就是非常著名的:面向对象编程。也是一切皆对象的最准确解释。
3 面向对象简介
Java是强类型语言,不同的数据都放入到了不同的类型中,但是JDK中提供的都是一些基本数据类型(如:int、double等),一些”复杂”的数据类型并没有给我们提供。而程序是为了解决现实生活问题的,像现实生活中的类型,放入到程序中时,就需要我们程序员自定义一个类型。
像这种把现实生活中类型变成程序中一个自定义类型的过程称为:抽象。每抽象出一个自定义类型,在对自定义类型实例化对象,这个对象就是程序中对应现实生活具体事物的。当在程序中操作这个对象时,就是在操作这现实生活中具体事物,这种编程方式称为面向对象编程(Object Oriented Programming,OOP)
4 面向对象编程
既然我们想要在程序与现实生活一一对应。就需要按照步骤学习下面几件事情。
- 如何自定义一个类型。让这个类型对应现实生活中的事物的类型。例如:如何定义一个手机类型。
- 如果对自定义类型创建对象。让这个对象对应现实生活具体事物的。例如:如何通过手机类型,实例化一个对象,让程序中这个对象对应华为mate40 5G,亮黑色 8+128G全网通。
二、 自定义类型
1 介绍
对于JDK中没有给我们提供的类型,就需要我们程序员自己定义。一个自定义类型中可以包含多个任意类型的数据,甚至可以在自定义类型包包含类型本身。这个定义过程是比较灵活的,不同的软件中相同类型可能包含不同的内容。
例如:我们之前写的简易超市管理系统中,每个商品需要包含名称和价格。其中名称是String类型,价格是double或int类型。而在京东中,一个商品可能包含:店铺、标题、卖点、价格、规格参数等多个信息,所以在京东中商品类型和我们写的商品类型稍微有点区别。所以一定要根据自己软件的需求来定义自己的类型。
其实自定义类型在Java中就是一个类(class),在类中提供了该类型包含的具体信息,每个信息数据都有它自己的类型。在Java中所有自定义类型都是引用类型。
2 语法
class 类名{
数据类型 名称;
数据类型 名称;
}
其中类名的命名规范和之前是相同的,大驼峰命名。类中数据类型支持我们所学的所有数据类型。名称命名规范和之前变量名的命名规范相同,小驼峰命名。
注意:在面向对象编程中,这种直接放在类下的变量称为:属性(field)。又称:全局变量。
3 自定义京东中手机类型
在京东中手机类型中包含的信息比较多,我们只保留里面的标题、价格、内存大小(单位G)、存储容量(单位G)。
三、 实例化对象及属性赋值
1 介绍
类对应现实中一类事物的类型,对象对应着具体的事物。现实中同一类型的不同事物都有着不同的特点。所以对于Java程序员必须要知道如何实例化对象,如何对对象进行赋值。
2 语法
类名 对象名 = new 类名();// 实例化对象语法
对象名.属性名= 值;// 给对象中属性赋值的语法
System.out.println(对象名.属性名); // 获取对象中属性,并输出到控制台
3 代码演示
以我们刚刚新建的手机类型作为基础。对手机类型进行实例化。
注意:不要直接在自定义类型中写主方法,虽然语法能通过,但是并不符合项目开发规范。所以在Product类的同包下新建了任意名称的类(示例中命名Test,表示测试类),并在类中提供主方法。
四、 访问权限修饰符
1 介绍
在Java中有包(package),包中允许有很多类,为了保证类中内容,Java中规定了使用不同的访问权限修饰符修饰的内容,有着不同的有效范围。
访问权限修饰符 中文名称 有效范围
public 公共的 任意位置
protected 受保护的 同包
什么也不写 友好的/默认的 同包
private 私有的 当前类
2 代码演示
在我们没有学习数据库和分层开发之前,一般习惯于把这种自定义类型放在xxx.xxx.pojo包中,其中xxx.xxx是公司网址倒写,pojo(Plain Ordinary Java Object) 中文名称:普通Java对象。而测试类习惯于放在xxx.xxx.test包中。
由于两个类已经不在同一包中了,所以需要使用public修饰Product中属性。
2.1 重新新建一个项目
新建项目jd2,项目结构如下
2.2 给Product中每个属性都使用public修饰
把Product类放在了com.bjsxt.pojo包中,并给每个属性添加public修饰。
2.3 测试类的代码
测试类中代码和之前是一样的。只是现在把测试类放在了com.bjsxt.test包中
五、 构造方法(Constructor)
1 介绍
每个对象实例化后都需要给对象的属性进行赋值,赋值的语法在上面已经讲过了,可以说:有多少属性,就需要有多少行赋值代码。Java为了简化对象属性赋值的代码,提供了构造方法。
当程序员不明确提供一个构造方法时,编译器会默认提供一个无参数构造方法。在我们实例化对象时new Product();中Product()就是无参数构造方法(构造方法是方法里面唯一通过new关键字调用的,其他都是xx.方法()的形式调用)。如果程序员显示提供了一个构造方法后,无论这个构造方法是无参的还是有参的,编译器都不会提供了默认无参构造方法。
2 无参构造方法
访问权限修饰符 类名(){
}
注意:
- 其他类实例化这个类时是需要通过构造方法实例化的。所以构造方法绝大多数都是用public修饰,来保证跨包也能调用。
- 构造方法名和类名完全相同。
- 构造方法只要写到类里面就行。但是我们习惯于把构造方法方法放在属性的下面。
具体代码示例:
也可以在构造方法中给属性一个初始值,这个初值是根据需求定义的,并不是说给予数据类型的默认值。
像上面的代码,每次实例化出来的对象中属性值都是一样的。但是很明显,不可能相同类型的事物特点都是完全相同的。
所以,如果可以在调用构造方法时,非常方便的给属性赋值,那就好了。
3 有参构造方法
像上面这种需要在调用方法时,给方法内部传递数据,这时就需要使用方法参数。(argument)。
方法参数就是在方法声明时,在方法括号里面声明一组变量(这些变量绝对不能赋初值),这些变量的有效范围是当前方法,也就是说在这个方法内部任意位置都能获取参数。当需要调用这个方法时按照顺序,按照类型,给予参数的值就可以了。
一个类中可以有多个构造方法,但是这些构造方法的参数个数或参数类型必须不同。一定在类中提供了有参构造方法,编译器不会提供默认的无参构造。为了防止其他人不知道这个类没有无参数构造而导致实例化对象失败的情况,我们都是只要提供了有参构造,都提供无参构造。
同一个方法参数中参数名称不允许重复。
3.1 代码示例一
在Product中提供了一个包含所有属性类型参数的构造方法。并把参数传递过来的值赋值给了类的属性。参数列表顺序不用和属性的顺序完全一致,但一般都是和属性顺序一致。
在com.bjsxt.test.Test中实例化Product对象时,代码量大大的减少。
一定要注意:调用构造方法时参数的顺序和每个参数的类型。
3.2 代码示例二
构造方法的参数个数不是必须和属性个数对应,如果类中只有部分属性是常用属性,也可以提供只包含部分参数的构造方法。
在com.bjsxt.test.Test类中实例化时按照顺序传递参数即可。由于内存大小和存储空间大小是没有赋值的,所以输出后为int默认值0
六、 this关键字
1 为什么使用this关键字
如果我们在定义构造方法时,把参数名和属性名定义成相同名称会什么样?
通过给title=title行进行断点调试会发现, 实例化对象时传递过来的值并没有赋值给全局变量,也就是说等号两侧的title都是方法参数,而不是属性。这是因为编译器的就近原则。
像这种全局变量和局部变量或方法参数名重名的情况就可以使用this关键字。
2 this关键字介绍
this关键字代表当前对象。即本次实例化出来的对象。我们通过new关键字实例化出来的对象能够调用什么内容,this关键字就可以调用什么内容,因为他俩都指向的是内存中一块地址。
通过this关键字可以调用类的全局变量。所以我们常常使用this.xxx = xxx;的形式来解决全局变量和方法参数或局部变量重名问题。
3 代码示例
通过this关键字,告诉编译器调用的是全局属性。
通过Debug可以发现,参数tile的值赋值给了全局变量title。
4 构造方法快捷键
在IDEA 菜单中 File -> Settings -> Keymap 中修改为Eclipse的情况下,可以通过:
Alt + Insert 快捷键选中Constructor
然后按住Ctrl选中所有属性名称(也可以先点击第一个属性,然后按住Shift之后点击最后一个属性)后,点击“OK”按钮,就可以生成所有参数的构造方法。里面点击几个属性就生成几个参数的构造方法。如果一个不选择,生成的就是无参构造方法。
七、 方法
1 方法简介
方法(Method)就是一大段代码,然后给这段代码起了一个名称,这个名称叫做方法名。
当我们需要复用一段代码时,或者想把一大段代码拆分成多块代码时,都可以使用方法。
在学习方法前期时,有的同学经常会考虑什么时候该定义一个方法,什么时候不该定义一个方法,其实没有明确规定。到后期就知道了,想定义一个方法就定义一个方法,不想定义方法,就把代码写到一起,效果也能实现。
在往后学习分层开发时,就知道:只要有一个新的功能就定义个方法。
优点:
- 实现代码的复用
- 功能分类更加明确
2 定义方法语法
访问权限修饰符 返回值类型 方法名(参数){
// 方法体(method body):一段代码
}
访问权限修饰符:支持所有访问权限修饰符。
返回值类型:方法执行完成后返回的结果类型。如果不需要返回结果使用void关键字。
方法名:自定义名称。小驼峰规范。
参数:可以有参数,也可以没有参数。与构造方法参数用法完全相同。定义方法时的参数称为:形参。
一个没有返回值的方法代码示例:
3 调用方法的语法
普通的方法必须通过对象调用。所以如果想要调用方法,前提先实例化方法所在类的对象。
语法:
类名 对象名 = new 类名();
数据类型 变量名 = 对象名.方法名(参数的值);
说明:
数据类型 变量名:只有当方法有返回值时才可以接收,数据类型与定义方法时返回值类型需要对应。代表着方法执行完成返回一个结果,复制给了新的变量存储。
参数值:如果定义方法有参数,就必须按照顺序传递参数的值。这时传递进去的值或变量称为:实参。
下图中1前面的i和2前面的j是IDEA的提示,提示把1赋值给了形参i,把2赋值给了形参j,并不是我们输入的内容。
如果方法实参是用变量的,对于形参和实参的名称是否重名是没有影响的。
九、 方法参数再次强调
方法定义时,提供了参数。其目的是为了让调用方法时给方法传递值。因为Java中有基本数据类型,又有引用数据类型,不同数据类型赋值时是不一样的。
基本数据类型:int i = 1; int j= i; j=2; 最终结果是i和j都指向全新的地址。j的改变并不影响i。所以我们经常说基本数据类型传递的是值。
引用数据类型:Product pro = new Product(); Product pro1 = pro; pro1.title=”新的值”; 由于pro和pro1都指向堆空间的同一个地址,所以pro1改变时,pro也跟随变化。
对于方法的参数的过程和变量赋值过程是一样的,实参赋值给形参的过程就是变量赋值是一样的。调用方法时给方法一个具体值,就是把这个值赋予到定义方法的参数中。所以一定要注意方法的参数是什么类型。如果是基本数据类型,方法内部改变参数的值,不会影响到调用方法时的变量。如果是引用数据类型参数,在方法内部改变参数值,会影响到实参的值。
十、 方法返回值的再次强调
方法是否有返回值是需要我们自己进行判断的,可以有返回值,也可以没有返回值。而且即使方法有返回值,并不意味着调用方法时必须接收返回值。
返回值就是方法执行完成给调用者的一个结果。这个结果是可以是任意类型的。
既然是返回结果那一定是在方法逻辑执行最后一行(注意是执行的最后一行,并不是代码的最后一行)。通过return 关键字返回。编译器会帮助判断,每个执行逻辑最后是否有返回值,如果没有返回值直接报编译错误。