六 面向对象语法(掌握)
6.1 面向对象
面向对象是基于面向过程的编程思想
-
面向对象的思想特点 ???A:是一种更符合我们思考习惯的思想 ???B:把复杂的事情简单化 ???C:让我们从执行者变成了指挥者 举例:
买电脑 , 洗衣服 , 做饭 , … , 万事万物皆对象
-
把大象装进冰箱(理解) ???A:面向过程实现 ???B:面向对象实现 注意:如何让我们的操作更符合面向对象思想呢? ???A:有哪些类 ???B:每个类有哪些成员 ???C:类与类的关系 -
类与对象 ???A:现实世界的事物 ??????属性: 事物的基本描述 ??????行为: 事物的功能 ???B:Java语言中最基本的单位是类。所以,我们要用类来体现事物 ???C:类包含: ??????成员变量 事物属性 ??????成员方法 事物行为 ???D:类:是一组相关的属性和行为的集合。是一个抽象的概念。 ?????对象:是该类事物的具体存在,是一个具体的实例。(对象) 举例:
学生:类 , 班长:对象
- 类的定义及使用
A:类的定义 成员变量 ???定义格式和以前一样,就是位置不同,在类中,方法外。 成员方法??? 定义格式和以前一样,就是去掉了static 。 B:使用类的内容 ???a:创建对象 ??????类名 对象名 = new 类名(); ???b:如何使用成员变量和成员方法呢 ??????对象名.成员变量 ??????对象名.成员方法()
6.2 成员变量和局部变量的区别(理解)
- 在类中的位置不同
???成员变量:?类中方法外 ???局部变量:?方法定义中或者方法声明上 - 在内存中的位置不同
???成员变量:?在堆中 ???局部变量:?在栈中 - 生命周期不同
???成员变量:?随着对象的创建而存在,随着对象的消失而消失 ???局部变量:?随着方法的调用而存在,随着方法的调用完毕而消失 - 初始化值不同
???成员变量:?有默认值 ???局部变量:?没有默认值,必须定义,赋值,然后才能使用
6.3 匿名对象(理解)
- 没有名字的对象
- 应用场景
A:调用方法,仅仅只调用一次的时候。 b:可以作为实际参数传递。
基本用法:
1:new Student().show();
2:new StudentTest().method(new StudentDemo());
package 匿名对象;
class StudentDemo {
public void method(Student s) {
s.show();
}
}
class Student {
public void show() {
System.out.println("我爱学习。");
}
}
public class NoNameDemo {
public static void main(String[] args) {
Student s = new Student();
s.show();
new Student().show();
new Student().show();
System.out.println("----------");
StudentDemo sd = new StudentDemo();
sd.method(new Student());
new StudentDemo().method(new Student());
}
}
6.4 封装(理解)
- 隐藏实现细节,提供公共的访问方式
- 好处:
???A:隐藏实现细节,提供公共的访问方式 ???B:提高代码的复用性 ???C:提高代码的安全性 - 设计原则
???把不想让外界知道的实现细节给隐藏起来,提供公共的访问方式 private 是封装的一种体现。 ???封装:类,方法,private 修饰成员变量
6.6 private关键字(掌握)
???1. 私有的意义,可以修饰成员变量和成员方法 ???2. 特点: ??????被private修饰的后的成员只能在本类中被访问 ???3. private的应用: ??????<1> 以后再写一个类的时候: ??????<2>把所有的成员变量给private了 ??????<3>提供对应的getXxx()/setXxx() 方法
6.7 this 、super 关键字(掌握)
-
代表当前类的引用对象 ???记住:哪个对象调用方法,该方法内部的this 就代表那个对象 -
this的应用场景: ???A:解决了局部变量隐藏成员变量的问题 ???B:其实this还有其他的应用,明天讲解。 -
super的用法和this很像 this代表本类对应的引用。 super代表父类存储空间的标识(可以理解为父类引用) -
用法(this和super均可如下使用) 访问成员变量 this.成员变量 super.成员变量 访问构造方法(子父类的构造方法问题讲) this(…) super(…) 访问成员方法(子父类的成员方法问题讲) this.成员方法() super.成员方法() 代码:
class Fu {
public final void show() {
System.out.println("这里是绝密资源,任何人都不能修改");
}
}
class Zi extends Fu {
}
class ZiDemo {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
6.8 构造方法(掌握)
- 作用:用于对对象的数据进行初始化
- 格式:
???A:方法名和类名相同 ???B:没有返回值类型,连void 都不能有 ???C:没有返回值 - 构造方法的注意事项
???A:如果我们没写构造方法,系统将提供一个默认的无参构造方法 ???B:如果我们给出了构造方法,系统将不再提供默认构造方法 ??????如果这个时候,我们要使用无参构造方法,就必须自己给出。 ??????推荐:永远手动自己给出无参构造方法。 - 给成员变量赋值的方式
???A:setXxx() ???B:带参构造方法 - 标准案例
class Student {
private String name;
private int age;
public Student(){}
public Student(String name,int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
测试:
class StudentDemo {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("林青霞");
s1.setAge(27);
System.out.println(s1.getName()+"---"+s1.getAge());
Student s2 = new Student("刘意",30);
System.out.println(s2.getName()+"---"+s2.getAge());
}
}
6.9 代码:Student s = new Student(); 做了哪些事情?(理解)
(1)把Student.class文件加载到内存
(2)在栈内存为s开辟空间
(3)在堆内存为学生对象申请空间
(4)给学生的成员变量进行默认初始化。null,0
(5)给学生的成员变量进行显示初始化。林青霞,27
(6)通过构造方法给成员变量进行初始化。刘意,30
(7)对象构造完毕,把地址赋值给s变量
6.11 static 关键字(理解)
- 静态的意思。可以修饰成员变量和成员方法。
- 静态的特点:
???A:随着类的加载而加载 ???B:优先与对象存在 ???C:被类的所有对象共享 ??????这其实也是我们判断该不该使用静态的依据。 ??????举例:饮水机和水杯的问题思考 D:可以通过类名调用 ??????既可以通过对象名调用,也可以通过类名调用,建议通过类名调用。 - 静态的内存图
???静态的内容在方法区的静态区 - 静态的注意事项;
???A:在静态方法中没有this对象 ???B:静态只能访问静态(代码测试过) - 静态变量和成员变量的区别
A:所属不同 ??????静态变量:属于类,类变量 ??????成员变量:属于对象,对象变量,实例变量 B:内存位置不同 ??????静态变量:方法区的静态区 ??????成员变量:堆内存 C:生命周期不同 ??????静态变量:静态变量是随着类的加载而加载,随着类的消失而消失 成员变量:成员变量是随着对象的创建而存在,随着对象的消失而消失 D:调用不同 静态变量:可以通过对象名调用,也可以通过类名调用 成员变量:只能通过对象名调用 - main方法是静态的
???public:权限最大 ???static:不用创建对象调用 ???void:返回值给jvm没有意义 ???main:就是一个常见的名称。 ???String[] args:可以接收数据,提供程序的灵活性
6.12 如何制作帮助文档(了解)
- 写一个类
- 加入文档注释
- 通过
javadoc 工具生成即可 ???javadoc -d 目录 -author -version ArrayTool.java
6.13 通过JDK提供的API学习了Math类(掌握)
- API(Application Programming Interface)
???应用程序编程接口(帮助文档) - Math类
???A:是针对数学进行操作的类 ???B:没有构造方法,因为它的成员都是静态的 ???C:产生随机数 ??????public static double random(): [0.0,1.0) ???D:如何产生一个1-100之间的随机数 ??????int number = (int)(Math.random()*100)+1; ???E:猜数字小游戏
package review.itcast01;
public class MathDemo {
public static void main(String[] args) {
System.out.println("PI:" + Math.PI);
System.out.println("E:" + Math.E);
System.out.println("--------------");
System.out.println("abs:" + Math.abs(10));
System.out.println("abs:" + Math.abs(-10));
System.out.println("--------------");
System.out.println("ceil:" + Math.ceil(12.34));
System.out.println("ceil:" + Math.ceil(12.56));
System.out.println("--------------");
System.out.println("floor:" + Math.floor(12.34));
System.out.println("floor:" + Math.floor(12.56));
System.out.println("--------------");
System.out.println("max:" + Math.max(12, 23));
System.out.println("max:" + Math.max(Math.max(12, 23), 18));
System.out.println("max:"
+ Math.max(Math.max(12, 78), Math.max(34, 56)));
System.out.println("--------------");
System.out.println("pow:" + Math.pow(2, 3));
System.out.println("--------------");
System.out.println("random:" + Math.random());
System.out.println("random:" + ((int) (Math.random() * 100) + 1));
System.out.println("--------------");
System.out.println("round:" + Math.round(12.34f));
System.out.println("round:" + Math.round(12.56f));
System.out.println("--------------");
System.out.println("sqrt:"+Math.sqrt(4));
}
}
案例:
import java.util.Scanner;
public class MathDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入开始数:");
int start = sc.nextInt();
System.out.println("请输入结束数:");
int end = sc.nextInt();
for (int x = 0; x < 100; x++) {
int num = getRandom(start, end);
System.out.println(num);
}
}
public static int getRandom(int start, int end) {
int number = (int) (Math.random() * (end - start + 1)) + start;
return number;
}
}
6.14 代码块(理解)
- 用
{} 括起来的代码。 - 分类:
???A:局部代码块 ??????用于限定变量的生命周期,及早释放,提高内存利用率。 ???B:构造代码块 ??????把多个构造方法中相同的代码可以放到这里,每个构造方法执行前,首先执行构造代码块。 ???C:静态代码块 ??????对类的数据进行初始化,仅仅只执行一次。 - 静态代码块,构造代码块,构造方法的顺序问题?
???静态代码块 > 构造代码块 > 构造方法
class Code {
static {
int a = 1000;
System.out.println(a);
}
{
int x = 100;
System.out.println(x);
}
public Code(){
System.out.println("code");
}
public Code(int a){
System.out.println("code");
}
{
int y = 200;
System.out.println(y);
}
static {
int b = 2000;
System.out.println(b);
}
}
class CodeDemo {
public static void main(String[] args) {
{
int x = 10;
System.out.println(x);
}
{
int y = 20;
System.out.println(y);
}
System.out.println("---------------");
Code c = new Code();
System.out.println("---------------");
Code c2 = new Code();
System.out.println("---------------");
Code c3 = new Code(1);
}
}
6.15 继承(掌握)
6.15.1 继承概述
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。 格式:
class 子类名 extends 父类名 {}
单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。 有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员。
6.15.2 继承好处
- 提高了代码的复用性
多个类相同的成员可以放到同一个类中 - 提高了代码的维护性
如果功能的代码需要修改,修改一处即可 - 让类与类之间产生了关系,是多态的前提
其实这也是继承的一个弊端:类的耦合性很强
6.15.3 继承的特点
- Java只支持单继承,不支持多继承。
一个类只能有一个父类,不可以有多个父类。
class SubDemo extends Demo{}
class SubDemo extends Demo1,Demo2...
class A{}
class B extends A{}
class C extends B{}
6.15.4 继承的注意事项
-
子类只能继承父类所有非私有的成员(成员方法和成员变量) 其实这也体现了继承的另一个弊端:打破了封装性 -
子类不能继承父类的构造方法,但是可以通过super(后面讲)关键字去访问父类构造方法。 不要为了部分功能而去继承 -
我们到底在什么时候使用继承呢? 继承中类之间体现的是:”is a”的关系。
6.15.5 继承中变量的关系
在子类方法中访问一个变量
- 首先在子类局部范围找
- 然后在子类成员范围找
- 最后在父类成员范围找(肯定不能访问到父类局部范围)
- 如果还是没有就报错。(不考虑父亲的父亲…)
6.15.6 继承中构造方法关系
子类中所有的构造方法默认都会访问父类中空参数的构造方法 为什么呢?
因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化。 每一个构造方法的第一条语句默认都是:super()
如何父类中没有构造方法,该怎么办呢?
子类通过super去显示调用父类其他的带参的构造方法。 子类通过this去调用本类的其他构造方法。 本类其他构造也必须首先访问了父类构造
一定要注意:
super(…)或者this(….)必须出现在第一条语句。 否则,就会有父类数据的多次初始化
看程序写结果:
- 把多个类中相同的成员给提取出来定义到一个独立的类中。然后让这多个类和该独立的类产生一个关系,
??? 这多个类就具备了这些内容。这个关系叫继承。 - Java中如何表示继承呢?格式是什么呢?
A:用关键字extends表示 B:格式: ???class 子类名 extends 父类名 {} - 继承的好处:
A:提高了代码的复用性 B:提高了代码的维护性 C:让类与类产生了一个关系,是多态的前提 - 继承的弊端:
A:让类的耦合性增强。这样某个类的改变,就会影响其他和该类相关的类。 ???原则:低耦合,高内聚。 ???耦合:类与类的关系 ???内聚:自己完成某件事情的能力 B:打破了封装性 - Java中继承的特点
A:Java中类只支持单继承 B:Java中可以多层(重)继承(继承体系) - 继承的注意事项:
A:子类不能继承父类的私有成员 B:子类不能继承父类的构造方法,但是可以通过super去访问 C:不要为了部分功能而去继承 - 什么时候使用继承呢?
A:继承体现的是:is a的关系。 B:采用假设法 - Java继承中的成员关系
A:成员变量 ???a:子类的成员变量名称和父类中的成员变量名称不一样,这个太简单 ???b:子类的成员变量名称和父类中的成员变量名称一样,这个怎么访问呢? 注意: ???<1> 子类的方法访问变量的查找顺序: ???<2> 在子类方法的局部范围找,有就使用。 ???<3> 在子类的成员范围找,有就使用。 ???<4> 在父类的成员范围找,有就使用。 ???<5> 找不到,就报错。 B:构造方法 a:子类的构造方法默认会去访问父类的无参构造方法 ???是为了子类访问父类数据的初始化 b:父类中如果没有无参构造方法,怎么办? ???子类通过super去明确调用带参构造 ???子类通过this调用本身的其他构造,但是一定会有一个去访问了父类的构造 ???让父类提供无参构造 C:成员方法 a:子类的成员方法和父类中的成员方法名称不一样,这个太简单 b:子类的成员方法和父类中的成员方法名称一样,这个怎么访问呢? ???通过子类对象访问一个方法的查找顺序: ??????<2> 在子类中找,有就使用 ??????<3> 在父类中找,有就使用 ??????<4> 找不到,就报错 - 两个面试题:
A:Override和Overload的区别?Overload是否可以改变返回值类型? B:this和super的区别和各自的作用? - 数据初始化的面试题
A:一个类的初始化过程 B:子父类的构造执行过程 C:分层初始化 - 案例:
A:学生和老师案例 ???继承前 ???继承后 B:猫狗案例的分析和实现 代码:
package com.itheima_02;
public class PhoneDemo {
public static void main(String[] args) {
NewPhone s1 = new NewPhone();
s1.call("刘宇");
}
}
class Phone{
public void call(String name){
System.out.println("给"+name+"打电话。");
}
}
class NewPhone extends Phone{
@Override
public void call(String name){
System.out.println("开启视频功能:");
super.call(name);
}
}
public class Demo {
public static void main(String[] args) {
Zi z = new Zi();
z.method();
z.show();
}
}
class Fu{
public void show(){
System.out.println("Fu中的show方法被调用。");
}
}
class Zi extends Fu{
public void method(){
System.out.println("Zi中的method方法被调用。");
}
public void show(){
super.show();
System.out.println("Zi中的show方法被调用。");
}
}
6.16 final 关键字(掌握)
- 是最终的意思,可以修饰类,方法,变量。
- 特点:
???A:它修饰的类,不能被继承。 ???B:它修饰的方法,不能被重写。 ???C:它修饰的变量,是一个常量。 - 面试相关:
A:局部变量 ???a:基本类型 值不能发生改变 ???b:引用类型 地址值不能发生改变,但是对象的内容是可以改变的 B:初始化时机 ???a:只能初始化一次。 ???b:常见的给值 ??????定义的时候。(推荐) ??????构造方法中。
6.17 多态(掌握)
-
同一个对象在不同时刻体现出来的不同状态。 -
多态的前提: A:有继承或者实现关系。 B:有方法重写。 C:有父类或者父接口引用指向子类对象。 多态的分类:
a:具体类多态
class Fu {}
class Zi extends Fu {}
Fu f = new Zi();
b:抽象类多态
abstract class Fu {}
class Zi extends Fu {}
Fu f = new Zi();
c:接口多态
interface Fu {}
class Zi implements Fu {}
Fu f = new Zi();
-
多态中的成员访问特点 A:成员变量 编译看左边,运行看左边 B:构造方法 子类的构造都会默认访问父类构造 C:成员方法 编译看左边,运行看右边 D:静态方法 编译看左边,运行看左边 为什么?
因为成员方法有重写。
-
多态的好处: A:提高代码的维护性(继承体现) B:提高代码的扩展性(多态体现) -
多态的弊端: 父不能使用子的特有功能。 现象:
子可以当作父使用,父不能当作子使用。
-
多态中的转型 A:向上转型 从子到父 B:向下转型 从父到子 -
孔子装爹的案例帮助大家理解多态 -
多态的练习 A:猫狗案例 B:老师和学生案例
6.18 抽象类(掌握)
- 把多个共性的东西提取到一个类中,这是继承的做法。
但是呢,这多个共性的东西,在有些时候,方法声明一样,但是方法体。 也就是说,方法声明一样,但是每个具体的对象在具体实现的时候内容不一样。 所以,我们在定义这些共性的方法的时候,就不能给出具体的方法体。 而一个没有具体的方法体的方法是抽象的方法。 在一个类中如果有抽象方法,该类必须定义为抽象类。 - 抽象类的特点
A:抽象类和抽象方法必须用关键字abstract修饰 B:抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类 C:抽象类不能实例化 D:抽象类的子类 a:是一个抽象类。 b:是一个具体类。这个类必须重写抽象类中的所有抽象方法。 - 抽象类的成员特点:
A:成员变量 有变量,有常量 B:构造方法 有构造方法 C:成员方法 有抽象,有非抽象 - 抽象类的练习
A:猫狗案例练习 B:老师案例练习 C:学生案例练习 D:员工案例练习 - 抽象类的几个小问题
A:抽象类有构造方法,不能实例化,那么构造方法有什么用? 用于子类访问父类数据的初始化 B:一个类如果没有抽象方法,却定义为了抽象类,有什么用? 为了不让创建对象 C:abstract不能和哪些关键字共存 a:final 冲突 b:private 冲突 c:static 无意义
6.19 制作帮助文档
具体的见我写的另外一篇博文,链接:Intellij IDEA如何生成JavaDoc
package DesignedPack;
class ArrayDemo2 {
public static void main(String[] args) {
int[] arr = {28,55,37,46,19};
ArrayTool2.printArray(arr);
int max = ArrayTool2.getMax(arr);
System.out.println("max:"+max);
int index = ArrayTool2.getIndex(arr,55);
System.out.println("index:"+index);
}
}
class ArrayTool {
private ArrayTool() {
}
public static void printArray(int[] arr) {
for (int x = 0; x < arr.length; x++) {
if (x == arr.length - 1) {
System.out.println(arr[x]);
} else {
System.out.print(arr[x] + ", ");
}
}
}
}
public class ArrayTool2 {
private ArrayTool2(){}
public static void printArray(int[] arr) {
System.out.print("[");
for(int x=0; x<arr.length; x++) {
if(x == arr.length-1) {
System.out.println(arr[x]+"]");
}else {
System.out.print(arr[x]+", ");
}
}
}
public static int getMax(int[] arr) {
int max = arr[0];
for(int x=1; x<arr.length; x++) {
if(arr[x] > max) {
max = arr[x];
}
}
return max;
}
public static int getIndex(int[] arr,int value) {
int index = -1;
for(int x=0; x<arr.length; x++) {
if(arr[x] == value) {
index = x;
break;
}
}
return index;
}
}
6.20 Random 类
package review.myRandom.itcast01;
import java.util.Random;
public class RandomDemo {
public static void main(String[] args) {
Random r = new Random(1111);
for (int x = 0; x < 10; x++) {
int num = r.nextInt(100) + 1;
System.out.println(num);
}
}
}
|