Java基础6

类与对象

类:具有相同特征的事物的抽象描述,是抽象的、概念上的定义。

对象:实际存在的该类事物的每个个体,是具体的,因而也称为实例。

 面向过程编程(POP)  vs     面向对象编程(OOP)

面向过程:以“函数”为组织单位,是一种“执行者思维”,适合解决简单问题。拓展能力差、后期维护难度较大。

面向对象:以“类”为组织单位,每种事物都具备自己的“属性”和“行为/功能”。是一种“设计者思维”,适合解决复杂问题、可维护性高。

两者之间的关系:我们千万不要把面向对象和面向过程对立起来,他们是相辅相成的,面向对象离不开面向过程。

 类

类是一组相关属性和行为的集合,这也是类最基本的两个成员。

属性: 该类事物的状态信息。对应类中的成员变量     成员变量<==>属性<==>Field

行为:该类事物要做什么操作,或者基于事物的状态能做什么。对应类中的成员方法    (成员)方法<==>函数<==>Method

类的实例化

类的实例化<==> 创建类的对象 <==> 创建类的实例

格式: 类类型 对象名 = 通过new创建的对象实体

举例:

Phone p1 = new Phone();

Scanner scan = new Scanner(System.in);

String str = new String();

面向对象完成具体功能的操作的三步骤:

① 创建类,并设计类的内部成员(属性、方法)

② 创建类的对象,比如Phone p1 = new Phone();

③ 通过对象,调用其内部声明的属性或方法,完成相关的功能

复制代码
public class Phone {
    // 属性
    String name;  //品牌
    double price; //价格
        
    //方法
    public void call(){
        System.out.println("手机能够打电话!");
    }
    
    public void sendMessage(String message){
        System.out.println("发送信息"+message);
    }
}


public class PhoneTest {
    public static void main(String []args) {
        //创建Phone对象
        Phone p1 = new Phone();
        
        //通过phone的对象,调用其内部的属性或方法
        //格式: "对象.属性" 或"对象.方法"
        p1.name = "huawei";
        p1.price = 4999;
        System.out.println("name = "+p1.name+", price = "+p1.price);
        
        //调用方法
        p1.call();
        p1.message("有内鬼!终止交易!!");
    }
}
复制代码

类中对象的内存解析

对象在内存中分配涉及的内存结构:

- 栈(stack) :方法内定义的变量,存储在栈中。

- 堆(heap) :  new出来的结构(比如:数组实体、对象的实体)。包括对象中的属性。

- 方法区(method area) :  存放类的模板。比如:Person类的模板。

说明:

Person P1 = new Person();  Person P2 = new Person();

创建类的多个对象时,每个对象在堆空间中有一个对象的实体。每个对象实体中保存着一份类的属性。如果修改某一个对象的某属性值时,不会影响其他对象的此属性。

Person P3 = new Person(); Person P3 = P1;

此时的P1,P3两个变量指向了堆空间中的同一个对象实体(P1,P3保存的地址值相同)。如果通过其中某一个对象变量修改对象的属性时,会导致另一个对象变量此属性的值变化。

 

 类的成员之一:属性

变量的分类:

角度一   按照数据类型来分:基本数据类型(8种)、引用数据类型(数组、类、接口、枚举、注解、记录)

角度二   按照变量在声明中的位置的不同: 成员变量(或属性)、局部变量(方法内、方法形参、构造器内、构造器形参、代码块内等)

成员变量 vs 局部变量

相同点:

>变量声明的格式相同: 数据类型  变量名  =  变量值

>变量都有其有效的作用域,出了作用域就会失效。

>变量必须先声明后赋值,再使用。

不同点:

① 类中声明的位置不同:   属性:声明在类内,方法外的变量   局部变量:声明在方法、构造器内部的变量

② 在内存中分配的位置不同:   属性:随着对象的创建,存储在堆空间中    局部变量:存储在栈空间中

③ 生命周期:   属性:随着对象的创建而创建,随着对象的消亡而消亡    局部变量:随着方法对应的栈帧入栈,局部变量会在栈中分配;随着方法对应的栈帧出栈,局部变量消亡

④ 作用域:    属性:在整个类的内部都是有效的    局部变量:仅限于声明此局部变量所在的方法(或构造器、代码块)中

⑤ 是否可以有权限修饰符进行修饰:  

    都有哪些权限修饰符: public、protected、缺省、private。(用于表明所修饰的结构可调用的范围大小)

    属性:是可以使用权限修饰符进行修饰的。    局部变量:不能使用任何权限修饰符进行修饰

是否有默认值:    属性:都有默认初始化值。意味着,如果没有给属性进行显示初始化赋值,则会有默认初始化值    局部变量:都没有默认初始化值。意味着在使用局部变量之前,必须要显示的赋值,否则报错。

复制代码
    //属性(或成员变量)
    String name;
    int age;
    char gender;
    
    //方法
    public void eat(){
        String food = "宫保鸡丁" // 局部变量
        System.out.println("我喜欢吃"+food);
    }
    
    public void sleep(int hour){ //形参: 同属于局部变量
        //编译不通过,因为超出了food变量的作用域  System.out.println("我喜欢吃"+food);
        System.out.println("人不能少于"+hour+"小时的睡眠");
    }
复制代码

案例:

1.声明一个MyDate类型,有属性:年year , 月month , 日day

2.声明一个Employee类型,包含属性:编号、姓名、年龄、薪资、生日(MyDate类型)

3.在EmployeeTest测试类中的main( )中,创建两个员工对象,并为他们的姓名和生日赋值,并显示

复制代码
class MyDate{
    int year;
    int month;
    int day;
}

class Employee{
    int id;
    String name;
    int age;
    double salary;
    MyDate birthday;  //可以用引用类型(类)作为属性的类型!
}

public class EmployeeTest{
    public static void main(String[] args){
        //创建一个Employee的实例
        Employee emp1 = new Employee();
        
        emp1.id = 1002;
        emp1.name = "小明";  // 也可以写 emp1.name = new String("小明");
        emp1.age = 24;
        emp1.salsry = 9000;
        emp1.birthday = new MyDate();
        emp1.birthday.year = 2000;
        emp1.birthday.month = 1;
        emp1.birthday.day = 24;
        /*
        另一种写法:
        * MyDate mydate1 = new MyDate();
        * emp1.birthday = mydate1;
        */
        System.out.println("id = " +emp1.id + ", name = "+ emp1.name+ ", age = "+emp1.age + ", salary = "+ emp1.salary + 
     ", biethday = [" +emp1.birthday.year+ "年"+emp1.birthday.month + "月"+emp1.birthday.day+"日]"); } }
复制代码

类的成员变量之二:方法

方法是类或对象行为特征的抽象,用来完成某个功能操作。在某些语言中也称为"函数" 或 "过程"

将功能封装为方法的目的: 实现代码重用、减少冗余、简化代码

注意

①Java里的方法不能独立存在,所有的方法必须定义在类里。

②方法内可以调用其他方法和属性。 

③方法内不可以定义方法

方法声明的格式

权限修饰符  [其他修饰符]  返回值类型  方法名(形参列表){ //方法头

   //方法体

}

权限修饰符: private / 缺省 / protected / public

返回值类型:描述当调用完此方法时,是否需要返回一个结果。  需要在方法内部配合使用“return + 返回值类型的变量或常量”

分类:

> 无返回值类型:使用void表示即可。比如: System.out.println(x)的println(x)方法

> 有具体的返回值类型: 需要指明返回的数据的类型。可以是基本数据类型,也可以是引用数据类型。

方法名: 属于标识符,需要满足标识符的规定和规范,要做到“见名知意”

形参列表: 形参,属于局部变量,且可以声明多个。   格式: (形参类型1  形参1,形参类型2  形参2,···)

分类:

>无形参列表: 不能省略这一对()。

>有形参列表: 根据方法调用时,需要的不确定的变量的类型和个数,确定形参的类型和个数。

方法体: 当我们调用一个方法时,真正执行的代码。体现了此方法的功能。

return关键字

作用: ①结束一个方法  ②结束一个方法的同时,可以返回数据给方法的调用者

方法调用的内存解析

- 形参:方法在声明时,一对()内声明的一个或多个形式参数,简称为形参。

- 实参:方法在被调用时,实际传递给形参的变量或常量,就称为实际参数,简称实参。

 对象数组

数组的元素可以是基本数据类型,也可以是引用数据类型。当元素是引用类型中的类时,就是对象数组。

举例:

String[] , Person[] , Student [] , Customer[]等

 

复制代码
class Student{
    int number;
    int sate;
    int score;
    
    public void PrintOut(){
        System.out.println("学号:"+number+",年级:"+state+",分数:"+score);
    }
}

public class StudentTest{
    public static void main(String[] args){
        //创建Student[]
        Student[] students = new Student[20];
        
        //使用循环赋值:
        for (int i = 0; i < students.length; i ++){
            students[i] = new Student();   //这一句忘记写就会是面向对象里面的空指针问题
            students[i].number = i+1;
            students[i].state = int(Math.random()*6+1);
            students[i].score = int(Math.random()*101);
        }
        
        //打印年级为3的学生信息:
        for (int i = 0; i < students.length; i ++){
            if (students[i].state == 3){
                students[i].PrintOut();
            }
        }
        
        //冒泡排序
        for (int i = 0; i < students.length-1; i ++){
            for (int j = 0; j < students.length-1-i; j ++){
                if (students[j].score > students[j+1].score){
                    Student stu = students[j];
                    students[j] = students[j+1];
                    students[j+1] = stu;
                }
            }
        }
        
        //打印所有学生信息
        for (int i = 0; i < students.length; i ++){
            students[i].PrintOut();
        }
    }
}  
复制代码

方法的重载

 定义:在一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可。

总结:“两同一不同” 同一个类、相同的方法名  参数列表不同(① 参数个数不同  ② 参数类型不同)

注意: 方法的重载与形参的名、权限修饰符、返回值类型都没有关系

练习: 判断与void show (int a,char b,double c){}构成重载的有:

1)void show(int x, char y, double z){}   //不是  因为形参列表都相同

2) int show (int a, double c, char b){}  //是的!不是因为前面的返回值类型是int  而是因为后面的形参列表是 int double char 跟上面不一样

3) void show (int a, double c, char b){}  //是的 后面的形参列表是int , double ,char

4) double show (int x, char y, double z){}  //不是!  虽然返回值类型不一样但是并不看返回值类型!!而是看后面的形参列表一样

可变个数形参的方法

在调用方法时,可能会出现方法形参的类型是确定的,但是参数的个数不确定。此时,我们就可以使用可变个数形参的方法。

格式:(参数类型 ... 参数名)

说明:

① 可变个数形参的方法在调用时,针对于可变的形参赋的实参个数可以为0个、1个或多个

② 可变个数形参的方法与同一个类中,同名的多个方法之间可以构成重载

③ 特例:可变个数形参的方法与同一个类中方法名相同,且与可变个数形参的类型相同的数组参数不构成重载

④ 可变个数的形参必须声明在形参列表的最后

⑤ 可变个数的形参最多在一个方法的形参列表中出现一次

复制代码
public class ArgsTest {
    public static void main(String []args) {
        ArgsTest test = new ArgsTest();
        
        test.print();  //输出 1111
        test.print(1);  //输出 1111
        test.print(1,2);  //输出 1111
    }
    
    //可变个数形参方法:
    public void print(int ... nums){
        System.out.println("1111");
    }
    
    /*
    public void print(inti){  //这个和上面的可变个数形参是属于重载
        System.out.println("2222");
    }
    
    public void print(int[] nums)   //这里的方法和上面的可变个数形参是一样的,编译不会通过!
    */
}
复制代码

 方法的值传递机制

1. 对于方法内声明的局部变量来说,如果出现赋值操作

   > 如果是基本数据类型的变量,则将此变量保存的数据值传递出去。

 > 如果是引用数据类型的变量,则将此变量保存的地址值传递出去。

2. 概念

形参:在定义方法时,方法名后面括号()中声明的变量称为形式参数,简称形参。

实参:在调用方法时,方法名后面括号()中使用的值/变量/表达式称为实际参数,简称实参。

3.方法的参数的值传递机制  实参给形参赋值的过程:

  > 如果形参是基本数据类型的变量,则将实参保存的数据值赋给形参。

  > 如果形参是引用数据类型的变量,则将实参保存的地址值赋给形参。

注意:Java中的参数传递机制是:值传递(不是引用传递)

复制代码
    public static void main(String[] args){
        ValueTransferTest test = new ValueTransferTest();
        // 1.对于基本数据类型的变量来说
        int m = 10;
        test.method1(m);
        System.out.println("m = "+m);  //这里得到的结果是10,方法里面改变的结果并不会影响main里面的m,只是把m的值赋给了形参
    }
    public void method1(int m){
        m++;
    }
复制代码
复制代码
    public static void main(String[] args){
        Person P = new Person();
        // 1.对于引用数据类型的变量来说
        P.age = 10;
        test.method2(P);
        System.out.println(P.age);  //这里得到的结果是11,把P的地址赋给了形参,所以main里面的值跟着一起改变
    }
    public void method2(Person P){
        P.age ++;
    }
复制代码

 现实中交换数值的常见错误:

复制代码
    //在冒泡排序中交换数组中的两个值  用方法写
    //swap(arr[i], arr[i+1]);  这种方法是错误的,并不会交换数组中值
    swap(arr, i , j);   //这样把引用数据类型传入进去就将地址传入了  可以达到交换数组值的目的
    
    public void swap(int i, int j){
        int temp = i;
        i = j;
        j = temp;
    }
    
    public void swap(int[] arr, int i, int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
复制代码

递归方法

自己调用自己的现象就称为“递归”  分类: 直接递归、间接递归

注意:递归调用会占用大量的系统堆栈,内存耗用多,在递归调用层次多时速度要比循环‘慢得多’,所以在使用递归时要慎重

      在要求高性能的情况下尽量避免使用递归,递归调用既花时间又‘耗内存’。考虑使用循环迭代

复制代码
public class PassObject {
    public static void main(String[] args){
        PassObject P1 = new PassObject();
        // 计算 1~n 的和,使用递归完成
        int n = 5;
        int sum = P1.getSum(n);
        System.out.println(sum);
    }

    public int getSum(int n){
        if (n == 1){
            return 1;
        }else{
            return n + getSum(n-1);
        }
    }
}
复制代码

package关键字的使用

说明:package 称为‘包’  用于指明该文件

注意:一个源文件只能有一个声明包的package语句,package语句作为Java源文件的第一条语句出现,若缺省该语句,则指定为无名包

包名: 属于标识符,满足标识符命名的规则和规范(全部小写)、见名知意

            - 包通常使用所在公司域名的倒置: com.atgujiu.XXX

    - 取包名不要使用 " java.xx "包

包对应于文件系统的目录,package语句中用 " . " 来指明包(目录)的层次, 每 . 依次就表示一层文件目录

同一个包下可以声明多个结构(类、接口),但是不能定义同名的结构(类、接口)。不同的包下可以定义同名的结构。

包的作用

  •  包可以包含类的子包,划分“项目层次”,便于管理
  • 帮助‘管理大型软件’系统:将功能相近的类划分到同一个包中。比如:MVC的设计模式
  • 解决‘类命名冲突’的问题
  • 控制‘访问权限’

import关键字的使用

import:导入

import语句显式引入指定包下所需要的类,相当于 'import语句告诉编译器到哪里去寻找类'

import语句,声明在包的声明和类的声明之间

如果使用 ' a.* '导入结构,表示可以导入a包下的所有的结构。如果在代码中使用不同包下的同名的类,那么就需要使用类的全类名的方式指明调用的哪个类。

 

posted on   gjwqz  阅读(3)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示