第5.1章 java面向对象
程序员最不缺的就是对象,你还没有?new一下不就有了?
- 第5.1章 java面向对象
- 什么是面向对象
- 封装
- 继承
- 多态
- 简单的回顾一下方法
- 类和对象的关系
- 创建于初始化对象
- 封装
- 初步认识修饰符private
- 继承
- 如果使用了静态方法:在实例化对象后 方法的调用只和左边,定义的类型有关系
- 如果使用了非静态方法:在实例化对象后,父类的引用(指针)指向了子类
什么是面向对象
-
面向对象编程(Object-Oriented Programming, OOP)
-
面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据
-
面向对象是一个抽象词汇
-
面向对象的三大特征:
-
从代码运行的角度来考虑是先有类后再有对象。类是对象的模板
-
面向对象思想
简单的回顾一下方法
-
方法的定义
- 修饰符
- 返回类型
//类 public class Demo01 { //主方法 main:一个真正的程序里面只有一个main方法 public static void main(String[] args) { } //修饰符 返回类型 方法名(..) public String sayHell0(){ //方法体 return "hello world";//return 返回值 } }
- break和return的区别:
- break:跳出switch 和循环
- return : 结束方法,返回一个结果
- 方法名:小驼峰式大小写 ,名称:见名之意
- 参数列表:(参数类型 参数名,…)
- 异常抛出
-
方法的调用
- 静态方法
- 非静态方法
注意:非静态方法不能在另一个类里面直接调用,需要先new一个实例对象后可以调用
- 形参和实参
public class Demo03 {
public static void main(String[] args) {
int sum=Demo03.add(1,2);//调用add静态方法并且传递两个实参1 和 2给形参a和b
System.out.println(sum);
}
public static int add(int a,int b){
return a+b;//获取到传递过来的实参后,进行相加并且返回该值
}
}
-
值传递和引用传递: 在java里面 java是值传递
-
//值传递 public class Demo04 { public static void main(String[] args) { int a=1; System.out.println(a);//1 Demo04.change(a); System.out.println(a);//1 } public static void change(int a){ a=10;//这个a为change方法形参的a } }
-
//引用传递 public class Demo05 { public static void main(String[] args) { Person person=new Person(); System.out.println(person.name);//null change(person); System.out.println(person.name);//limuqing } public static void change(Person person){ person.name="limuqing"; } } class Person{ String name; }
-
this关键字
public class ThisDemo01 { public int a=0; public void setA(int a){ this.a=a;//this.a为public int a=0; //a为方法的形参啊 } }
类和对象的关系
-
类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物
创建于初始化对象
Person类里面什么东西都没有,为什么还能被我们给实例化成功呢?
我们使用IDEA反编译方法来查看Person.class源文件的内容
为什么源文件里面多出了一个 像方法却又不像方法的东西????
这个东西就是构造方法,每个类都至少有一个构造方法并且它是隐藏显示,你也可以将它写出来。构造方法也可以由我们自己定义但是需要注意以下几点:
-
1.构造器的方法名必须和类名相同
-
2.构造器没有放回类型,更没有返回值
-
定义有参构造之后,如果想使用无参构造,就需要显示的定义一个无参构造
构造器的作用:
-
1.new的本质在调用构造方法
-
2.初始化对象的值
我们常常可以用这个默认的构造器来给一些字段赋值一些初始值
当然也可以我们自己创建构造方法,这个创建也就是方法的重载
可以说构造方法是一个特殊的方法。
IDEA快捷键alt+insert
- alt+insert
结合刚才所学对下面程序进行一次简单的内存分析
这里我使用的是在线流程图工具 Process On。注册进入流程图即可
首先:程序会进入这个程序入口main方法,因此加载出了Application这个类里面的方法和一些常量。并且在栈里面记录main方法
然后:然后进入了main方法里面运行了第一个语句Pet dog=new Pet(); 实例了一个动物类命名为dog。这是在栈里面就会有有一个dog引用变量名。并且在堆里面的方法区里面也会加载出Pet类里面的字段和方法。这时dog引用变量名指向了对立面的地址为 0x0001的代码快,这里面所有的字段默认赋值。
运行到main()方法里面的第三句代码时:根绝dog指向的ox0001的内存空间块改变name的值。第四句同理。第五句就根据dog指向的0x0001代码块,而0x0001加载的是方法区里的Pet类里的方法,所以可以直接调用shout()方法
第五六句,直接输出dog的name和age的值。
第八句:有实例化了一个Pet类引用变量名为cat然后入栈,入栈后在堆里面创建一个新的内存区域为0x0002.
程序结束。cat出栈、dog出栈、main出栈。堆里面的内存区域进入回收站
封装
初步认识修饰符private
在往常我们实例化后就可以对这个类里面的字段进行赋值,但是这次我们在Student类里面对字段进行了private(私有的)进行了修饰后,无法访问该变量了。我们在堆该字段进行简单的数据保护的同时,却也保护过头无法使用该变量。这时我们可以通过一些方法来对此进行赋值:
这时可能有些小伙伴就会有疑问。为什么不直接将private改成public后对这个字段进行赋值呢,还要这般多此一举。那么我们在看一个案例:
案例1:模拟用户输入自己的年龄(使用public修饰符)
案例2:模拟用户输入自己的年龄(使用private修饰符加封装get|set)
继承
-
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模
-
extends 的意思是"扩展".子类是父类的扩展
-
JAVA中:类只有单继承,并没有多继承!
-
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等
-
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类使用关键字extends来表示
-
子类和父类之间,从意义上将应该具有“is a"的关系
特殊情况为:private修饰符所修饰的方法和字段继承给子类,但是子类无法进行访问
在观看继承关系时,我们发现了我们明明没有给Person使用继承,但是确还是有了一层继承关系。我这时先去看看其他的类是否也是如此
我们发现String工具类没写继承关系,但是也还是默认继承了Object类。
由此可以得出所有的类都会直接或者间接的继承Object类
在刚才查看String工具类源码的时候我们发现在public final class String{…} 跟我们平常有点一样。多了一个final的关键字。我们来看看有了这个关键字后会有什么影响
方法没有重写之前
方法重写之后
多态:
但是如果我们使用static关键来修饰方法呢
由实践得出静态方法和非静态方法的区别很大
重写需要注意的点:需要有继承关系,子类重写父类的方法!
1.方法名必须相同
2.参数列表必须相同
3.修饰符:范围可以扩大:但是不能缩小 比如父类有一个方法是的修饰符是default,在子类重写的时候可以将修饰符改成public
4.修饰的大小关系 public > protected >default >private
5.抛出的异常:范围可以被缩小,但不能扩大;
重写,子类的方法和父类必须要一致,只有方法名不同!
那么为什么要重写呢?
1.父类的功能,子类不一定需要,或者满足不了子类的需求