当前位置: 首页 > news >正文

Java语法-类和对象(上)

1. 面向对象的初步认识

        1.1 什么是面向对象

                概念: Java是一门纯面向对象的语言(Object Oriented Program,简称OOP),在面向对象的世界里,一切皆为对象


        1.2 面向对象VS面向过程   

                如:洗衣服

                面向过程: 注重的是洗衣服的过程,少了一个环节也不行.而且不同衣服洗的方式,时间长度,拧干方式都不同,处理起来就比较麻烦。如果将来要洗鞋子,那就是另一种放方式。按照该种方式来写代码,将来扩展或者维护起来会比较麻烦。

                面向对象:   java中一切皆对象

                1. 找对象

                2. 创建对象

                3. 使用对象

                总共四个对象:人,衣服,洗衣机,洗衣粉

                整个过程: 把衣服倒进洗衣机,放入洗衣粉,启动洗衣机

                总:可以看出该过程是人,衣服,洗衣机,洗衣粉四个对象之间交互完成的,不需要关注具体某个过程是什么

          

2. 类的定义和类的实例化

       

        面相对象程序设计关注的是对象,而对象是现实生活中的实体,比如:洗衣机。但是洗衣机计算机并不认识,需要开发人员告诉给计算机什么是洗衣机。

上图就是对洗衣机简单的描述,该过程称为对洗衣机对象(实体)进行抽象(对一个复杂事物的重新认知),洗衣机有哪些属性如:品牌,型号,功率...有哪些功能(方法): 干洗,快洗...

        2.1 认识类

        概念: 类就是一个用来描述一个事物的东西,描述该事物有哪些属性,有哪些功能.

        2.2 定义类

        java中定义类需要使用class关键字:

class 类名 { 属性;

                    方法  }

        类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者类成员变量。方法主要说明类具有哪些功能,称为类的成员方法。

        2.3 实例化类

        定义了一个类,就相当于在计算机中定义了一种新的类型(和int double类似,不过我更倾向于引用类型String),用类类型创建对象的过程,称为类的实例化.

        我们采用new关键字配合类名字来实例化对象

                首字母大写类名 自定义名字 = new 首字母大写类名();

        好了,我们来定义一个狗类:

//TODO 每个类会产生一个字节码文件
class PetDog {public String name;//名字public String color;//颜色public static int ID;// 狗的属性public void barks() {System.out.println(name + ": 旺旺旺~~~");}//狗的行为public void wag() {System.out.println(name + ": 摇尾巴~~~");}public static void main(String[] args) {//实例化 实例化出来的东西就是一个真正的实体//用类类型创建对象的过程叫类的实例化//TODO 定义了一个类,就相当于在计算机中定义了一种类型PetDog dog = new PetDog();PetDog dog2 = new PetDog();PetDog dog3 = new PetDog();System.out.println(dog);//存的是这个对象的地址dog.name = "小白";System.out.println(dog.name);dog.barks();dog.wag();dog2.name = "小黑";dog2.barks();dog2.wag();System.out.println(PetDog.ID);//静态的要用类名来调用}
}

注意事项:

  •         类名注意采用大驼峰定义
  •         成员前写法统一为public,后面会详细解释
  •         此处写的方法不带 static 关键字. 后面会详细解释
  •         使用.来访问对象中的属性和方法
  •         同一个类可以创建多个实例

        2.4 类和对象的说明

                1. 类只是一个模型一样的东西,用来对一个实体进行描述,限定了类有哪些成员.

                2. 类是一种自定义的类型,可以用来定义变量.

                3. 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量

                4. 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间

总之这么理解: 类其实就是一种事物的模板,对象就是具体根据整个模板构造出来的东西.

3 .this引用

        this表示当前对象的引用

        3.1 为什么要有this?

                我们来看一个代码

public void setDay(int year, int month, int day){year = year;month = month;day = day;
}

        如上述代码可知,我们不晓得这个方法里面的形参和成员变量谁是是谁.谁给谁赋值,并且后续我们创建多个对象之后,如果都使用setDay这个成员方法,就更加分不清谁是形参谁是当前对象的成员变量了.这时候this的作用就出来了.

        3.2 什么是this引用

         this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

        像上述代码,我们就可以这么写:

package Class_Object;public class Class_Object_This {public int year;public int month;public int day;public void setDate(int year,int month,int day) {//方法只有一个,你怎么知道在给谁赋值?this.year = year;this.month = month;this.day = day;//year = year 这个表示局部变量对自己赋值}public static void main(String[] args) {Class_Object_This date = new Class_Object_This();date.setDate(1999,1,1);System.out.println(date.year + " " +date.month + " " + date.day);Class_Object_This date1 = new Class_Object_This();date1.setDate(1990,2,1);System.out.println(date1.year + " " +date1.month + " " + date1.day);}}

        在setDate这个方法里面我们就能够分清楚形参和成员变量了,因为this是当前对象的引用,每个创建出来的对象都有一块自己的地址空间,因此this也是唯一的,也就能够区分出来了,this.year就是创建出来的对象的成员变量.

        3.3 this引用的特性

                1. this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型

                2. this只能在"成员方法"中使用

                3. 在"成员方法"中,this只能引用当前对象,不能再引用其他对象

                4. this是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法对象的引用传递给该成员方法,this负责来接收

4. 对象的构造以及初始化

         4.1 构造方法

                这个方法很特殊,就是在创建对象的时候会把对象里面的属性一起赋值,不需要再这么赋值 "对象名.属性=赋值",或者调用自己的方法来进行赋值,而是在创建对象的时候就会自动调用该方法,把赋值的东西通过参数传过去.

                好了介绍一下构造方法的写法:名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次.即: public 类的名字(){}

                

public class Date {
public int year;
public int month;
public int day;
// 构造方法:
// 名字与类名相同,没有返回值类型,设置为void也不行
// 一般情况下使用public修饰
// 在创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
public Date(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
System.out.println("Date(int,int,int)方法被调用了");
}
public void printDate(){
System.out.println(year + "-" + month + "-" + day);
}
public static void main(String[] args) {
// 此处创建了一个Date类型的对象,并没有显式调用构造方法
Date d = new Date(2021,6,9); // 输出Date(int,int,int)方法被调用了
d.printDate(); // 2021-6-9
}
}

        注意: 构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间     

        4.2 构造方法的特性:

                1. 名字必须与类名相同

                2. 没有返回值类型,设置为void也不行

                3. 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)

                4. 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)

            构造方法不止一个,可以有多个构造方法构成重载(名字相同,参数列表不同)
 

public class Date {public int year;public int month;public int day;
// 无参构造方法public Date(){this.year = 1900;this.month = 1;this.day = 1;}
// 带有三个参数的构造方法public Date(int year, int month, int day) {this.year = year;this.month = month;this.day = day;}public void printDate(){System.out.println(year + "-" + month + "-" + day);
}public static void main(String[] args) {Date d = new Date();d.printDate();
}
}

注意:如果你自己没写构造方法,系统会给你默认生成一份不带参数的构造方法.一旦你自己写了,就不生成.(救急不救穷)

        并且构造方法里面也可以调用其他的构造方法(使用this)

        

public class Date {public int year;public int month;public int day;
// 无参构造方法--内部给各个成员赋值初始值,该部分功能与三个参数的构造方法重复
// 此处可以在无参构造方法中通过this调用带有三个参数的构造方法
// 但是this(1900,1,1);必须是构造方法中第一条语句
public Date(){
//System.out.println(year); 注释取消掉,编译会失败this(1900, 1, 1);
//this.year = 1900;
//this.month = 1;
//this.day = 1;
} /
/ 带有三个参数的构造方法
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
}

        其中this()必须是构造方法的第一条语句(但是不能成环,也就是俩个构造方法不能相互调用)

5. 封装和访问权限

        5.1 封装的概念

         面向对象的三大特性: 封装,继承,多态.继承和多态我们后期再讲,先说封装.

        封装: 将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行 交互.差不多就是套壳屏蔽细节.比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器,USB插孔等,让用户来和计算机进行交互,完成日常事务。但实际上:电脑真正工作的却是CPU、显卡、内存等一些硬件元件

         对于用户而言,我们只需要使用鼠标键盘,即可,不需要关注具体电脑里面的部件和构成

        5.2 访问修饰限定符:

                在具体了解封装之前我们需要看一下访问修饰限定符.ava中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,更符合人类对事物的认知,而访问权限用来控制方法或者字段能否直接在类外使用。Java中提供了四种访问限定符:

                像之前我们定义类或者方法前面就有这个玩意,public就是一个访问修饰限定符,它规定了这个类或者方法的访问范围是多少.是否能够在当前包内访问,是否支持跨包访问....

        public: 表示无论你在哪,是谁都可以访问到

        default: 表示在创建自己的这个包内可以访问到(当你什么都不写的时候就是dedault)

        private: 表示这个只有自己晓得,其他人都不晓得

        protected: 后续讲了继承再说

public class Computer {
private String cpu; // cpu
private String memory; // 内存
public String screen; // 屏幕
String brand; // 品牌---->default属性
public Computer(String brand, String cpu, String memory, String screen) {
this.brand = brand;
this.cpu = cpu;
this.memory = memory;
this.screen = screen;
}
public void Boot(){
System.out.println("开机~~~");
}
public void PowerOff(){
System.out.println("关机~~~");
}
public void SurfInternet(){
System.out.println("上网~~~");
}
}
public class TestComputer {
public static void main(String[] args) {
Computer p = new Computer("HW", "i7", "8G", "13*14");
System.out.println(p.brand); // default属性:只能被本包中类访问
System.out.println(p.screen); // public属性: 可以任何其他类访问
// System.out.println(p.cpu); // private属性:只能在Computer类中访问,不能被其他类访问
}
}

        被private修饰的属性,然后你试图在其他类通过 "对象.这个属性"来访问它,但是访问不到,这个过程体现的就是封装.

        那有没有方法来访问被private修饰的属性呢,是有的,我们可以通过get和set方法来对被private修饰的属性进行设置和访问.

package Class_Object;public class People {private String name;private int age;public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return this.name;}public People(String name, int age) {this.name = name;this.age = age;}}
class Test{public static void main(String[] args) {People people = new People("小白",18);
//        people.name = "小黑";name被private修饰,我们无法在不同类里面访问它people.setName("小黑");//我们可以通过set方法来设置这个private修饰的属性System.out.println(people.getName());//再调用getName这个方法来获得这个属性的值}
}

6. static成员

        被static修饰的成员方法或者成员变量是属于类的,是类方法,类变量,是独一份的.像普通成员方法和变量,我们创建一个新的对象就会开辟新的空间,每个对象就都会有一份成员方法和成员变量.而被static修饰的类方法和类变量是属于类的,只有一份.

        6.1 学生类例子:

public static void main(String[] args) {
Student s1 = new Student("Li leilei", "男", 18, 3.8);
Student s2 = new Student("Han MeiMei", "女", 19, 4.0);
Student s3 = new Student("Jim", "男", 18, 2.6);
}
}

假设三个同学是同一个班的,那么他们上课肯定是在同一个教室,那既然在同一个教室,那能否给类中再加一个成员变量,来保存同学上课时的教室呢?答案是不行的。

之前在Student类中定义的成员变量,每个对象中都会包含一份(称之为实例变量),因为需要使用这些信息来描述具体的学生。而现在要表示学生上课的教室,这个教室的属性并不需要每个学生对象中都存储一份,而是需要让所有的学生来共享。在Java中,被static修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对象,是所有对象所共享的。

        6.2 static修饰的成员方法和变量

                static修饰的成员变量,称为静态成员变量,静态成员变量最大的特性:不属于某个具体的对象,是所有对象所共享的。

【静态成员变量特性】

1. 不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中

2. 既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问

3. 类变量存储在方法区当中

4. 生命周期伴随类的一生(即:随类的加载而创建,随类的卸载而销毁)

public class Student{
public String name;
public String gender;
public int age;
public double score;
public static String classRoom = "Bit306";
// ...
public static void main(String[] args) {
// 静态成员变量可以直接通过类名访问
System.out.println(Student.classRoom);
Student s1 = new Student("Li leilei", "男", 18, 3.8);
Student s2 = new Student("Han MeiMei", "女", 19, 4.0);
Student s3 = new Student("Jim", "男", 18, 2.6);
// 也可以通过对象访问:但是classRoom是三个对象共享的
System.out.println(s1.classRoom);
System.out.println(s2.classRoom);
System.out.println(s3.classRoom);
}
}

        static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。静态成员一般是通过静态方法来访问的

public class Student{
// ...
private static String classRoom = "Bit306";
// ...
public static String getClassRoom(){
return classRoom;
}
}public class TestStudent {
public static void main(String[] args) {
System.out.println(Student.getClassRoom());
}
输出:Bit306

【静态方法特性】

1. 不属于某个具体的对象,是类方法

2. 可以通过对象调用,也可以通过类名.静态方法名(...)方式调用,更推荐使用后者

3. 不能在静态方法中访问任何非静态成员变量

        总之:我个人认为,当某个属性的值是确定的时候,比如班级,我们就可以使用static修饰这个属性,同一样,当这个方法也是不需要变动的时候,我们也使用static来修饰这个方法.这样就可以节省很多的空间.

7. 代码块

        使用 {} 定义的一段代码称为代码块。根据代码块定义的位置以及关键字,又可分为以下四种:

        7.1 普通代码块: 定义在方法中的代码块(少见)

public class Main{
public static void main(String[] args) {
{ //直接使用{}定义,普通方法块
int x = 10 ;
System.out.println("x1 = " +x);
} in
t x = 100 ;
System.out.println("x2 = " +x);
}
} /
/ 执行结果
x1 = 10
x2 = 100

        7.2 构造块: 定义在类中的代码块(不加修饰符)。也叫:实例代码块。构造代码块一般用于初始化实例成员变量。

public class Student{
//实例成员变量
private String name;
private String gender;
private int age;
private double score;
public Student() {
System.out.println("I am Student init()!");
} /
/实例代码块
{
this.name = "bit";
this.age = 12;
this.sex = "man";
System.out.println("I am instance init()!");
}
public void show(){
System.out.println("name: "+name+" age: "+age+" sex: "+sex);
}
}
public class Main {
public static void main(String[] args) {
Student stu = new Student();
stu.show();
}
} /
/ 运行结果
I am instance init()!
I am Student init()!
name: bit age: 12 sex: man
public class Student{
private String name;
private String gender;
private int age;
private double score;
private static String classRoom;
//实例代码块
{
this.name = "bit";
this.age = 12;


 

       7.3 静态块: 使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量。
 

public class Student{
private String name;
private String gender;
private int age;
private double score;
private static String classRoom;
//实例代码块
{
this.name = "bit";
this.age = 12;
this.gender = "man";
System.out.println("I am instance init()!");
} /
/ 静态代码块
static {
classRoom = "bit306";
System.out.println("I am static init()!");
}
public Student(){
System.out.println("I am Student init()!");
}
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student();
}
}

        同步代码块(后续讲解多线程部分再谈)

       7.4  整体的实例:

package Class_Object;public class Student {public String name;public int age;public int ID;public static String classRoom ;//静态的成员变量不属于对象,属于类public Student(){//重载//在构造方法里面调用其他构造方法,不能自己调用自己this("小黑",89);}public Student(String name,int age) {this.name = name;this.age = age;System.out.println("我是构造方法");}static {//静态代码块//一般用来初始化静态成员变量//一般在类加载被调用classRoom = "337";System.out.println("这个是静态代码块");}{//对普通成员变量进行初始化this.ID = 2022011;System.out.println("这个是构造代码块/实例代码块");//实例化的时候调用}public void eat() {System.out.println(this.name + "正在吃饭");
//alt +insert这个可以快速生成构造方法}public static void fuc(){//func这个静态方法直接通过类名就能调用,不依赖对象System.out.println("静态的方法");
//        System.out.println(this.name);//name的调用需要对象的引用来调用,依赖对象,所以会报错}//TODO toString@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", ID=" + ID +'}';}public static void main(String[] args) {//静态先执行(只执行一次)//执行构造代码块//构造方法Student student = new Student("小白",19);
//        student.eat();System.out.println("==============");Student student1 = new Student("小黑",19);{System.out.println("我是普通代码块");}System.out.println(student1.toString());//打印对象内容System.out.println(student1);//打印对象内容}}
//执行结果:
这个是静态代码块
这个是构造代码块/实例代码块
我是构造方法
==============
这个是构造代码块/实例代码块
我是构造方法
我是普通代码块
Student{name='小黑', age=19, ID=2022011}
Student{name='小黑', age=19, ID=2022011}

    由上述代码我们可以知道:    

        静态代码块不管生成多少个对象,其只会执行一次

        静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的

        如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行(合并)实例代码块只有在创建对象时才会执行

8. 对象的打印

        在上一个代码中,我们就用到了对象的打印方法:toString(), 这个方法就是来打印对象的属性,但是如果不重写(后续讲)就只会打印地址:


class Student {public String name;public int age;public Student(String name, int age) {this.name = name;this.age = age;}
}
public class Test {public static void main(String[] args) {Student student = new Student("小白",18);//我们没有重写toString方法,直接调用System.out.println(student.toString());}
}
//运行结果:
Student@1540e19dProcess finished with exit code 0

        如果我们重写了toString()方法,就可以成功打印出对象的属性值了


class Student {public String name;public int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {//这个就是重写的toString方法return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
public class Test {public static void main(String[] args) {Student student = new Student("小白",18);//重写了之后再调用System.out.println(student.toString());}
}
//运行结果:
Student{name='小白', age=18}Process finished with exit code 0


http://www.mrgr.cn/news/35118.html

相关文章:

  • 软件测试必学的16个高频数据库操作及命令
  • Numpy入门及进阶(三)
  • LabVIEW导入并显示CAD DXF文件图形 程序见附件
  • 数学建模模型算法-Python实现
  • SSE (Server-Sent Events) 服务器实时推送详解
  • Qt 获取当前系统中连接的所有USB设备的信息 lsusb版
  • Ubuntu USB设备绑定
  • project generator 简单使用(二)之 CLion 与 AC6
  • top 使用技巧
  • 基于vue框架的刺梨销售管理系统pgl49(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
  • 大势智慧亮相“第十届博博会”,展现数字文旅新质生产力!
  • React 中实现 vue keep-alive 功能的方法
  • web群集--rocky9.2部署zabbix服务端的详细过程
  • 如何使用ECharts制作折线图
  • 用于体积医学图像分割的跨视角差异依赖网络|文献速递--基于多模态-半监督深度学习的病理学诊断与病灶分割
  • 软件验收测试报告有什么作用?第三方验收测试报告包括哪些内容?
  • EasyCVR全方位安全守护智慧电厂:构建高效视频监控系统优势分析
  • 【源码】Sharding-JDBC源码分析之ShardingSphereConnection的创建原理
  • 分享C++程序员面试八股文(九)
  • 《动手学深度学习》笔记2.1——神经网络从基础→进阶 (模型构建→参数初始化→设计层/块→磁盘读写→多GPU加速)
  • RPC框架开发——理解项目功能
  • 可看见车辆行人的高清实时视频第2辑
  • unity CustomEditor的基本使用
  • vue强制刷新组件的三种方式:$forceupdate、v-if、key
  • Spring Boot 学习之路 -- 处理 HTTP 请求
  • 基于深度学习的花卉智能分类识别系统