Javase||四、面向对象(上)
文章目录
1、类和对象
类:抽象概念的人
对象:实实在在的人
1.1类和对象的创建
步骤(面向对象思想落地的实现:
 1、创建类、设计类的成员
 2、创建类的对象
 3、通过“对象.属性”或“对象.方法”调用对象的结构
体会类的多个对象的关系:如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性(非static的), 意味着如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值
创建类:
class Person {
    //属性
    String name;
    int age = 1;
    boolean isMale;
    //方法
    public void eat() {
        System.out.println("爱吃蔬菜");
    }
    public void sleep() {
        System.out.println("不熬夜");
    }
    public void language(String talk) {
        System.out.println("李华可以说话,使用的是:"+talk);
    }
}
创建类的对象:
public class PersonTest {
    public static void main(String[] args) {
        //创建Person类的对象
        Person p1 = new Person();
        //Scanner scanner = new scanner(system.in);
        //调用对象的结构:属性、方法
        
        //调用属性:“对象.方法”
        p1.name = "李华";
        p1.age = 23;
        p1.isMale = true;
        System.out.println(p1.name);
     
        //调用方法,“对象.方法”
        p1.eat();
        p1.sleep();
        p1.language("中文");
1.2JVM内存结构
略
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gmXF5Eqi-1650111114178)(D:\Liqingq\techique\markdown_notebook\学习\java\学习配图\IJW%B5RK9IR{JOC[FCV87.png)]
1.3匿名对象
定义:我们创建的对象,没显示的赋给一个变量名。即为匿名对象
特点:匿名对象只能调用一次
举例:
 new Phone().price=1999;
 new Phone().showPrice();//0.0
应用场景:
public class InstanceTest {
    public static void main(String[] args) {
        PhoneMall mall = new PhoneMall();
        //匿名对象的使用
        mall.show(new Phone());
    }
}
class PhoneMall {
    public void show(Phone phone) {
        phone.sendEmail();
        phone.playGame();
    }
}
class Phone {
    double price;
    public void sendEmail() {
        System.out.println("发送邮件");
    }
    public void playGame() {
        System.out.println("玩游戏");
    }
    public void showPrice(){
        System.out.println("价格为:"+price);
    }
}
2、类的结构之一:属性
类的结构:属性和方法
设计类就是设计类的成员:
-  属性 = 成员变量 = field 
-  方法 = 成员变量 = 函数 = method 
-  创建类的对象 = 类的实例化 = 实例化类 /*如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性(非static的) 意味着如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值*/
这里注意不同点,成员变量直接定义在类的一对{}内;
局部变量:声明在方法内、方法形参、代码块内、构造器内部的
属性默认初始化值情况
类的属性,根据其类型,都有默认初始化值;
局部变量没有默认初始化值,故调用局部变量之前,一定要显示赋值,特别的,形参在调用时,我们赋值
2.1(成员变量)属性与局部变量的对比
-  相同点: - 定义变量格式相同:数据类型 变量名 = 变量值
- 先声明后使用
- 变量都有其对应的作用域
 
-  不同点 2.1类中声明位置不同:属性:直接在类的{}中;局部变量:声明在方法内、方法形参、代码块形参、构造器内部的变量 2.2权限修饰符不同 属性:可以在声明时,指明其权限,使用权限修饰符 java规定的4中权限修饰符:private、public 、缺省、protectd2.3默认初始化值情况: 属性:类的属性,根据其类型,都有默认初始化值 整型(byte、short、int、long) : 0 浮点型(float、doble):0.0 字符型(char):0(或’\u0000‘) 布尔型(boolean):false 引用数据类型(类、数组、接口):null 
 局部变量,没有初始化值(意味着,在调用局部变量之前,一定要显示赋值。
 特别的,形参在调用时,我们赋值即可。
 2.4 内存加载位置:
属性:加载在堆空间中(非static)
局部变量:加载在栈空间中
3、类的结构之二:方法
1、方法:描述类应该具有的功能
比如:Math类:sqrt()\random()\...
     Scanner类:nextxxx()
     Arrays类:sort()\binarySeach()\toString\equals()\...
2、方法分类:
          无返回值                  有返回值
无形参     void方法名(){}          返回值的类型方法名(){}
有形参     void方法名(形参列表){}   返回值的类型方法名(形参列表){}
举例:
     public void eat(){}
     public void sleep(int hour){}
     public String getName(){}
     public String getNation(String nation) {}
      形
3、方法的声明:权限修饰符 返回值类型 方法名(形参列表){
                    方法体
                    }
         注意:static、final、abstrat来修饰的方法(权限修饰符)
4、说明:
    4.1关于权限修饰符,默认方法的权限修饰符先都使用public
       java规定的4中权限修饰符:private、public 、缺省、protectd
    4.2返回值类型:有返回值vs无返回值
    4.2.1如果方法有返回值,则必须再方法生命时,指定返回值的类型,同时,方法中,
    需要使用return关键字来返回指定类型的变量或常量。
    如果方法中没有返回值,则方法声明时2,使用void来表示,没有返回值的方法中,就不使用
    return,但是,如果使用的话,只能“return"表示此方法结束的意思。
    4.2.2我们定义方法时,该不该有返回值?
    1、题目要求
    2、凭经验,具体问题具体分析
    4.3方法名:属于标识符,遵循标识符的规则和规范,“见名之意”
    4.4形参列表:方法可以声明0个,1个,或多个
        4.4.1格式:数据类型1  形参1,数据类型2,形参2,···
        4.4.2我们定义方法时,该不该定义形参
          1.题目要求
          2.凭经验
   
3.1方法举例与声明的方式
1、方法:描述类应该具有的功能
比如:Math类:sqrt()\random()\...
     Scanner类:nextxxx()
     Arrays类:sort()\binarySeach()\toString\equals()\...
2、方法分类:
          无返回值                  有返回值
无形参     void方法名(){}          返回值的类型方法名(){}
有形参     void方法名(形参列表){}   返回值的类型方法名(形参列表){}
举例:
     public void eat(){}
     public void sleep(int hour){}
     public String getName(){}
     public String getNation(String nation) {}
      形
3、方法的声明:权限修饰符 返回值类型 方法名(形参列表){
                    方法体
                    }
         注意:static、final、abstrat来修饰的方法
4、说明:
    4.1关于权限修饰符,默认方法的权限修饰符先都使用public
       java规定的4中权限修饰符:private、public 、缺省、protectd
    4.2返回值类型:有返回值vs无返回值
    4.2.1如果方法有返回值,则必须再方法生命时,指定返回值的类型,同时,方法中,
    需要使用return关键字来返回指定类型的变量或常量。
    如果方法中没有返回值,则方法声明时2,使用void来表示,没有返回值的方法中,就不使用
    return,但是,如果使用的话,只能“return"表示此方法结束的意思。
    4.2.2我们定义方法时,该不该有返回值?
    1、题目要求
    2、凭经验,具体问题具体分析
    4.3方法名:属于标识符,遵循标识符的规则和规范,“见名之意”
    4.4形参列表:方法可以声明0个,1个,或多个
        4.4.1格式:数据类型1  形参1,数据类型2,形参2,···
        4.4.2我们定义方法时,该不该定义形参
          1.题目要求
          2.凭经验
   return关键字的作用:
        1.使用范围:方法体中
        2.作用:2.1 结束方法
                2.2针对有返回值类型的方法,使用return数据方法返回所要的数据
        3.注意:return关键字后面不可以声明执行语句
   5.方法的使用中,可以调用当前类的属性或方法
           特殊的:方法A中又调用了方法A(递归方法)
练习
public class StudentTest {
    public static void main(String[] args) {
        Student[] stus = new Student[20];//Student类型的数组,与String[] stus = new student[20]一样的意思
        for (int i = 0; i < stus.length; i++) {
            //给数组元素赋值
            stus[i] = new Student();//给每个数组位置new一个对象
            stus[i].number = i + 1;
            stus[i].score = (int) (Math.random() * (100 - 0 + 1));
            stus[i].state = (int) (Math.random() * (6 - 1 + 1) + 1);
        }
        StudentTest s1 = new StudentTest();
        s1.print(stus);
        s1.searchState(stus, 3);
        s1.sort(stus);
        s1.print(stus);
    }
    //遍历学生数组
    public void print(Student[] stus) {//传入要打印的数组
        for (int i = 0; i < stus.length; i++) {
            System.out.println(stus[i].info());
        }
    }
    public void searchState(Student[] stus, int state) {
        System.out.println("**************************");
        for (int i = 0; i < stus.length; i++) {
            if (stus[i].state == 3) {
                System.out.println("number:" + stus[i].number + ",state" + stus[i].state
                        + ",score" + stus[i].score);
            }
        }
    }
    public void sort(Student[] stus) {
        System.out.println("**************************");
        for (int i = 0; i < stus.length - 1; i++) {
            for (int j = 0; j < stus.length - 1 - i; j++) {
                if (stus[j].score < stus[j + 1].score) {
                    Student temp = stus[j];
                    stus[j] = stus[j + 1];
                    stus[j + 1] = temp;
                }
            }
        }
    }
}
class Student {
    int number;
    int state;
    int score;
    public String info() {
        return "number:" + number + ",state" + state
                + ",score" + score;
    }
}           
3.1关键字return
return关键字的作用:
1.使用范围:方法体中
 2.作用:
2.1 结束方法
 2.2针对有返回值类型的方法,使用return数据方法返回所要的数据
 3.注意:return关键字后面不可以声明执行语句
3.2方法的重载
重载的概念:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数
类型不同即可。
 //重载
    public void getSum(int i, int j) {
        System.out.println("1");
    }
    public void getSum(double d1, double d2) {
        System.out.println("2");
    }
    public void getSum(String s, int i) {
        System.out.println("3");
    }
3.3可变参数个数形参的方法
- 声明格式:方法名(参数的类型名 …参数名)
- 可变参数:方法参数部分指定类型的参数个数是可变多个:0个,1个或多个
- 可变个数形参的方法与同名的方法之间,彼此构成重载
- 方法的参数部分有可变形参,需要放在形参声明的最后
- 在一个方法的形参位置,最多只能声明一个可变个数形参
 public void  show(String s){
        System.out.println("show(String)");
    }
    //可变个数的形参,与上面的show()方法构成重载
    public void show(String...strs){
        System.out.println("show(String...strs)");
    }
//    public void show(String [] str){
//
//    }此方法与可变个数的形参认为是一样的,不构成重载
//注意:如果有个方法,方法名和上面一样,但是,形参是有限个,优先调用有限个的方法
}
3.4java的值传递机制(注意理解)
==待理解:视频p213练习继续敲代码=
Java的实参值如何传入方法呢?
 Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
- 形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参
- 形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参
- 注意String类型虽然它是引用类型,但是实际上它是基本数据类型的使用方法,传值
基本数据类型:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DtlxcLfX-1650111114179)(D:\Liqingq\techique\markdown_notebook\学习\java\学习配图\G6~JT5@2)]Q6WB3345(W.png)
引用数据类型:
值传递的运用:**
package day09;
public class Circle {
    double radius;
    public double findArea() {
        return Math.PI * radius * radius;
    }
}
package day09;
//值传递的运用
public class PassObject {
    public static void main(String[] args) {
        PassObject object = new PassObject();
        Circle c = new Circle();
        object.printAreas(c, 5);
        System.out.println("now radius is " + c.radius);
    }
    public void printAreas(Circle c, int time) {
        System.out.println("Radius\t\tArea");
        for (int i = 1; i <= time; i++) {
            c.radius = i;
            System.out.println(c.radius + "\t\t\t" + c.findArea());
        }
        c.radius = time + 1;
    }
}
3.4递归方法
略
4、面向对象特征之一:封装性
4.1封装的含义
为什么需要封装?封装的作用和含义?
-  我要用洗衣机,只需要按一下开关和洗涤模式就可以了。有必要了解洗衣机内部的结构吗?有必要碰电动机吗? 
-  我们程序设计追求“高内聚,低耦合”。 
高内聚 :类的内部数据操作细节自己完成,不允许外部干涉;低耦合 :仅对外暴露少量的方法用于使用。
- 隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。
总结:封装属性的方法是为了信息的安全性,防止客户乱用。比如封装属性legs,如果用户使legs=-11,不切实际。而我们如果把legs封装起来,在方法中对legs设权限(例如:legs>0&&legs<3),而客户只能通过调用此方法才能使用legs,就不会造成乱用
4.2封装性思想具体的代码体现:
- 将类属性私有化,同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值
- 不对外暴露的私有化方法
- 单例模式(将构造器私有化)。通俗来说,就是只能在类的内部造一个对象,不能在外面调用构造器造对象
- 不希望类在包外被调用,可以将类设置为缺省的
4.2Java规定的四种权限修饰符
| 修饰符 | 类内部 | 同一个包 | 不同包的子类 | 同一个工程 | 
|---|---|---|---|---|
| private | Yes | |||
| (缺省) | Yes | Yes | ||
| protected | Yes | Yes | Yes | |
| public | Yes | Yes | Yes | Yes | 
==注意:==对于class的权限修饰只可以用public和default(缺省)
5、类的结构之三:构造器
5.1作用:
- 创建对象;Order o = new Order();
- 给对象进行初始化;Person p = new Person(“Peter”,15);
5.2语法格式:
public class Animal {
private int legs;
// 构造器:
//修饰符 类名 (参数列表) {
//初始化语句;
//} 
public Animal() {
legs = 4;
} 
public void setLegs(int i) {
legs = i;
}
public int getLegs() {
return legs;
}
}
5.3五条说明:
- 一个类可以创建多构造器,彼此构成重载
- 父类的构造器不可被子类继承
- 默认构造器的修饰符与所属类的修饰符一致
- 如果没显示的定义类的构造器的话,则系统默认提供一个空参的构造器。(因为类造对象必须调用构造器)
- 一个类中,至少会有一个构造器
5.4总结: 赋值的先后顺序
① 默认初始化
 ② 显式初始化
 ③ 构造器中初始化
 ④ 通过“对象.属性“或“对象.方法”的方式赋值
 赋值的先后顺序:
 ① - ② - ③ - ④
5.6JavaBean概念
JavaBean是一种Java语言写成的可重用组件。
所谓javaBean,是指符合如下标准的Java类:
- 类是公共的
- 有一个无参的公共的构造器
- 有属性,且有对应的get、set方法
6、关键字:this
6.1理解this
- 它在方法内部使用,即这个方法所属对象的引用
- 它在构造器内部使用,表示该构造器正在初始化的对象。
- this 可以调用类的属性、方法和构造器
什么时候使用this关键字呢?
当在方法内需要用到调用该方法的对象时,就用this。具体的:我们可以用this来区分属性和局部变量。
 比如:this.name = name;
6.2使用this,调用属性、方法
-  在任意方法或构造器内,如果使用当前类的成员变量或成员方法可以在其前面添加this,增强程序的阅读性。不过,通常我们都习惯省略this。 
-  当形参与成员变量同名时,如果在方法内或构造器内需要使用成员变量,必须添加this来表明该变量是类的成员变量 
-  使用this访问属性和方法时,如果在本类中未找到,会从父类中查找 
6.3注意:
- "this(形参列表)"必须声明在类的构造器的首行!
- 在类的一个构造器中,最多只能声明一个"this(形参列表)"
- 可以在类的构造器中使用"this(形参列表)"的方式,调用本类中重载的其
 他的构造器!
- 明确:构造器中不能通过"this(形参列表)"的方式调用自身构造器
7、关键字:pachage/import
7.1JDK中主要的包介绍
- java.lang----包含一些Java语言的核心类,如String、Math、Integer、 System和
 Thread,提供常用功能
- java.net----包含执行与网络相关的操作的类和接口。
- java.io ----包含能提供多种输入/输出功能的类。
- java.util----包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日
 期日历相关的函数。
- java.text----包含了一些java格式化相关的类
- java.sql----包含了java进行JDBC数据库编程的相关类/接口
- java.awt----包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这
 些类被用来构建和管理应用程序的图形用户界面(GUI)。
7.2import
格式:import 包名. 类名;
注意:
- 在源文件中使用import显式的导入指定包下的类或接口
- 声明在包的声明和类的声明之间。
- 如果需要导入多个类或接口,那么就并列显式多个import语句即可
- 举例:可以使用java.util.*的方式,一次性导入util包下所有的类或接口。
- 如果导入的类或接口是java.lang包下的,或者是当前包下的,则可以省略此import语句。
- 如果在代码中使用不同包下的同名的类。那么就需要使用类的全类名的方式指明调用的
 是哪个类。
- 如果已经导入java.a包下的类。那么如果需要使用a包的子包下的类的话,仍然需要导入。
- import static组合的使用:调用指定类或接口下的静态的属性或方法
  // 全类名方式
        com.atguigu.exer3.Account acc1 = new com.atguigu.exer3.Account(1, 131, 12);
- java.sql----包含了java进行JDBC数据库编程的相关类/接口
- java.awt----包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这
 些类被用来构建和管理应用程序的图形用户界面(GUI)。
7.2import
格式:import 包名. 类名;
注意:
- 在源文件中使用import显式的导入指定包下的类或接口
- 声明在包的声明和类的声明之间。
- 如果需要导入多个类或接口,那么就并列显式多个import语句即可
- 举例:可以使用java.util.*的方式,一次性导入util包下所有的类或接口。
- 如果导入的类或接口是java.lang包下的,或者是当前包下的,则可以省略此import语句。
- 如果在代码中使用不同包下的同名的类。那么就需要使用类的全类名的方式指明调用的
 是哪个类。
- 如果已经导入java.a包下的类。那么如果需要使用a包的子包下的类的话,仍然需要导入。
- import static组合的使用:调用指定类或接口下的静态的属性或方法
  // 全类名方式
        com.atguigu.exer3.Account acc1 = new com.atguigu.exer3.Account(1, 131, 12);










