【Java SE】类和对象

目录

1、面向对象

1.1、什么是面向对象

1.2、面向对象和面向过程的区别

2、类

 2.1、字段/属性/成员变量

 成员变量默认值:

 成员变量和局部变量的区别

2.2 方法

 2.3 null 空引用

2.4、类的实例化(对象)

3、this 关键字

 3.1 this引用

3.2  为什么使用 this

3.3 this 引用的特性

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

4、 对象的构造及初始化

 4.1 构造方法

 4.2 特性

4.3 初始化

 5、封装

访问限定符

 6、static关键字

6.1 static修饰成员变量

 6.2 static修饰成员方法

 7、代码块

 总结

 8、内部类

 8.1 静态内部类

注意:

8.2  非静态内部类

8.3 匿名内部类


1、面向对象

1.1、什么是面向对象

Java是一门纯面向对象的语言(Object Oriented Program,简称OOP),在面向对象的世界里,一切皆为对象。面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事情。用面向对象的思想来设计程序,更符合人们对事物的认知,对于大型程序的设计、扩展以及维护都非常友好.

1.2、面向对象和面向过程的区别

1.面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;

2.面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。

2、类

1、就是一类对象的统称对象就是这一类具体化的一个实例,通过关键字new 实例化对象

2、声明一个类就是自己定义一个类型(自定义类型),而类在 Java 中属于引用类型Java 使用关键字 class 来声明类。

基本语法

// 创建类
class ClassName{ 
  field;    // 字段(属性) 或者 成员变量
  method;    // 行为 或者 成员方法
}
  • class定义类的关键字ClassName类的名字{}中为类的主体
  • 类中的元素称为:成员属性。类中的函数称为:成员方法。
  • 类名注意采用大驼峰
 class  Date{
    //成员变量  成员属性  实例变量
    //字段-》属性-》成员变量->类的内部 方法的外部的-》1、普通成员变量  静态成员变量
    public int year;
    public int month;
    public int day;
    
    //成员方法->行为->1、普通成员方法  静态成员方法
    public void Print(){
        System.out.println("年月日");
    }
}
  1. 一般 一个文件当中只定义一个类
  2. public 修饰的类必须和文件相同
  3. 不要在 代码直接修改 public 修饰的类 ,要通过开发工具(重命名)

 2.1、字段/属性/成员变量

类中方法外部定义的变量. 这样的变量我们称为 "字段" 或 "属性" 或 "成员变量"(三种称呼都可以, 一般不会严格区分)

注意事项

  • 使用 . 访问对象的字段.
  • "访问" 既包含读, 也包含写.
  • 对于一个对象的字段如果没有显式设置初始值, 那么会被设置一个默认的初值

 成员变量默认值:

基本类型

默认值

boolean

false

char

\u0000

byte

0

short

0

int

0

long

0L

float

0.0f

double

0.0d

 成员变量和局部变量的区别

区别

成员变量

局部变量

类中位置不同

类中方法外

类中方法里

内存中位置

堆内存

栈内存

生命周期不同

随对象存在而存在

随方法调用而存在,结束而释放

初始化值不同

默认初始值

没有默认初始值,必须定义并赋值

2.2 方法

 用于描述一个对象的行为.

class student{
    //字段-》属性-》成员变量->类的内部 方法的外部的
    public string name;
    public int age;

    //成员方法->行为->1、普通成员方法
    public void show() {
 	System.out.println("我叫" + name + ", 今年" + age + "岁");
}
class Test {
  public static void main(String[] args) {
    Person person = new Person();
    person.show();
 }
}

 2.3 null 空引用

null 在 Java 中为 "空引用", 表示不引用任何对象. 类似于 C 语言中的空指针. 如果对 null 进行 . 操作就会引发异常.

class Person {
  public String name;
  public int age;
}
class Test {
  public static void main(String[] args) {
    Person person = new Person();
    System.out.println(person.name.length());  // 获取字符串长度
 }
}
// 执行结果
Exception in thread "main" java.lang.NullPointerException
    at Test.main(Test.java:9
  1. 当一个引用 赋值为 null —> 这个对象不指向任何对象;
  2. 引用不能指向引用,而是指向 另一个引用指向的对象;
  3. 一个引用只能指向一个对象;

2.4、类的实例化(对象)

定义了一个类,就相当于在计算机中定义了一种新的类型(自定义类型);

用类类型创建对象的过程,称为类的实例化,在java中采用new关键字,配合类名来实例化对象。

// 创建类
class <class_name>{ 
    
  field;//成员属性
  method;//成员方法
}
// 实例化对象
<class_name> <对象名> = new <class_name>()

注意事项

  • new 关键字用于创建一个对象的实例.
  • 使用 . 来访问对象中的属性和方法.
  • 同一个类可以创建对个实例(一对多)

3、this 关键字

 3.1 this引用

this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。

this 代表的就是 当前对象的引用,在new 对象是开辟内存时,this 就指向了当前对象

public class Date {
  public int year;
  public int month;
  public int day;
  public void setDay(int year, int month, int day){
    this.year = year;
    this.month = month;
    this.day = day;
 }
  public void printDate(){
    System.out.println(this.year + "/" + this.month + "/" + this.day);
 }
}

 注意:this引用的是调用成员方法的对象。

3.2  为什么使用 this

public void setDay(int year, int month, int day){
  year = year;
  month = month;
  day = day;
}
  •  成员变量自己赋值自己、 优先局部变量,错误赋值
  • 使用this 指名赋值对象成员变量
public void setDay(int year, int month, int day){
  this.year = year;
  this.month = month;
  this.day = day;
}

3.3 this 引用的特性

  1. this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
  2. this只能在"成员方法"中使用 (静态不能使用)
  3. 在"成员方法"中,this只能引用当前对象,不能再引用其他对象

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

this 访问构造方法

  • this 必须在第一行
  • 必须在构造方法内部

4、 对象的构造及初始化

 4.1 构造方法

构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。

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. 名字必须与类名相同,修饰符 必须是 public
  2. 没有返回值类型,设置为void也不行
  3. 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)
  4. 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)
    •  写了 有参构造,向在调用无参构造,必须自己写出来
    • 只要有自定义的构造方法,系统就不会在提供默认构造
  5. 如果用户没有显式定义,编译器会生成一份默认的构造方法,生成的默认构造方法一定是无参的;定义了有参构造,但是没有写无参构造,new一个无参,编译不通过,报错
  6. 构造方法中,可以通过this调用其他构造方法来简化代码
 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();
 }

上述两个构造方法:名字相同,参数列表不同,因此构成了方法重载

public class Date {
  public int year;
  public int month;
  public int day;
    //有参构造
  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();
 }
}

 注意:

  1. 没有定义任何构造方法,编译器会默认生成一个不带参数的构造方法。
  2. 一旦用户定义,编译器则不再生成。
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(...)必须是构造方法中第一条语句
  • 不能形成环
public Date(){
 this(1900,1,1);
}
public Date(int year, int month, int day) {
 this();
}
/*
无参构造器调用三个参数的构造器,而三个参数构造器有调用无参的构造器,形成构造器的递归调用
编译报错:Error:(19, 12) java: 递归构造器调用
*/

4.3 初始化

1.  默认初始化:不给参数,成员会被赋 初始值(基本类型),自定义类型,会调用构造方法

2. 就地初始化就地初始化,就是在 声明成员变量是直接给了初始值

 5、封装

 面向对象(OOP)的三个基本特征:封装、继承、多态

封装:就是将数据和操作方法 隐藏起来,不让外部直接访问,必须通过公开外部接口对对象交互访问

规则:

  1. 将类内部的某些数据方法隐藏起来,不允许直接访问
  2. 只能通过类提供接口进行 交互

实现:

  1. 修改属性私有(private)
  2. 创建 set/get 方法(public修饰,提供外部使用)
  3. 在set/get 方法中设置条件进行判断限制

class Person {
  private String name;
  private int age;

  public Person(){
  }
  public void setage(int age){
      if(age>30){
          this.age = 18;
      }else{
     	 this.age = age;
      }
  }
  public int gettage(){
      return age; 
  }
}

访问限定符

范围

private

default

protected

public

同一包中的同一类

同一包中的不同类

不同包中的子类

不同包中的非子类

 6、static关键字

6.1 static修饰成员变量

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);
  }
}
class TestDemo{
  public int a;
  public static int count;
}
public class Main{
 
public static void main(String[] args) {
    TestDemo t1 = new TestDemo();
    t1.a++;									// 1
    TestDemo.count++;						// 1
    System.out.println(t1.a);
    System.out.println(TestDemo.count);
    System.out.println("============");
    TestDemo t2 = new TestDemo();
    t2.a++;									// 1
    TestDemo.count++;						// 2  静态的  累计相加 属于类
    System.out.println(t2.a);		
    System.out.println(TestDemo.count);
 }
}

 count被static所修饰,所有类共享。且不属于对象,访问方式为:类名 . 属性。

 6.2 static修饰成员方法

被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。

静态成员变量一般是通过静态方法来访问的

【静态方法特性】

  1. 不属于某个具体的对象,是类方法
  2. 可以通过对象调用,也可以通过类名.静态方法名(...)方式调用
  3. 不能在静态方法中直接访问任何非静态成员变量
//静态成员方法
public static String getClassRoom(){
    //不能引用 非静态变量  this
  System.out.println(this);
  return classRoom;
}
// 编译失败:Error:(35, 28) java: 无法从静态上下文中引用非静态 变量 this

public static String getClassRoom(){
  age += 1;
  return classRoom;
}
// 编译失败:Error:(35, 9) java: 无法从静态上下文中引用非静态 变量 age

静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递this引用 

//静态成员方法
public static String getClassRoom(){
    //不能引用 非静态 方法
  doClass();
  return classRoom;
}

 7、代码块

普通代码块:定义在方法中的代码块

构造代码块:定义在类中的代码块(不加修饰符)

  • 也称 实例代码块 ,构造代码块一般用于初始化实例成员变量

静态代码块:定义在类中的 被 static 修饰的代码块

一般用于初始化静态成员变量

注意:

  • 静态代码块 不管 new 了多少实例对象,只会执行一次
  • 静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的;
  • 如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行(合并)
  • 实例代码块只会在 创建对象时执行
class Student{
    public String name = "liuhuangshu";
    public int age;
    public static String classRoom;
    // 静态代码块  只会执行一次
    static {
        //初始化 静态成员变量
        classRoom = "java1";
        System.out.println("静态代码块 初始化静态的数据成员");
    }
    //构造代码块  在构造方法前执行
    {    
        name = "caocao";
        System.out.println("非静态代码块/实例代码块/构造代码块 初始化非静态的数据成员");
    }

    public Student(){
        System.out.println("无参的构造!");
    }


    public Student(String name,int age){
        this.name = name;
        this.age = age;
        System.out.println("带有两个参数的构造!");
    }

    public void show(){
        {
            System.out.println("普通代码块");
        }
        System.out.println("name:"+name+" age:"+age);
    }
}
public static void main(String[] args) {
    Student student1  = new Student();
    System.out.println("===============");
    Student student2  = new Student();
    student1.show();
}

 总结

1、代码块执行顺序

静态代码块(只执行一次) —> 构造代码块(new 对象执行)—> 构造方法 —>方法中的 普通代码块

2、构造代码块 和 构造方法的区别

构造代码块:只要 new 对象,有参、无参 都会执行 此代码块

构造方法:new 对象,只会调用 匹配的代码块

 8、内部类

在 Java 中,可以将一个类定义在另一个类或者一个方法的内部,前者称为内部类,后者称为外部类。内部类也是封装的一种体现

  1. 静态内部类
  2. 实例内部类(非静态内部类)

注意

  1. 定义在class 类名{}花括号外部的,即使是在一个文件里,都不能称为内部类;
  2. 内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件

 8.1 静态内部类

被static修饰的内部成员类称为静态内部类

class OuterClass1 {
    public  int date1 = 1;
    private int date2 = 2;
    public static int date3 = 3;

    //静态内部类
    static class staticInClass{
        public  int date4 = 4;
        private int date5 = 5;
        public static int date6 = 6;
        //
        public void func(){
            System.out.println("staticInClass->func");
            OuterClass1 outerClass1 = new OuterClass1();
            //静态 内部类 不能调用外部类非静态 成员变量
            System.out.println(outerClass1.date1);
            System.out.println(outerClass1.date2);
            System.out.println(date3);
            System.out.println(date4);
            System.out.println(date5);
            System.out.println(date6);
        }
    }
    //外部类
    public void func(){
        System.out.println("OuterClass1->func");
        //外部类 不能调用内部类非静态 成员变量
        staticInClass staticInClass = new staticInClass();
        System.out.println(date1);
        System.out.println(date2);
        System.out.println(date3);
        System.out.println(staticInClass.date4);
        System.out.println(staticInClass.date5);
        //外部类 可以直接调用 内部类的静态成员
        System.out.println(staticInClass.date6);    
    }
}

注意:

1.  静态内部类 不能调用 外部类的非静态成员

 2. 静态内部类 未实例化 外部类不能调用非静态成员

 3. 静态内部类初始化:

public static void main(String[] args) {
    //初始化 内部静态类
    OuterClass1.staticInClass staticInClass = new OuterClass1.staticInClass();
    staticInClass.func();
}

注意:

  1. 静态内部类中只能访问外部类中的静态成员,想访问非静态,在静态内部类中实例化外部类
  2. 创建静态内部类对象时,不需要先创建外部类对象

8.2  非静态内部类

未被static修饰的成员内部类

package inclass;
class OuterClass2 {
    public  int date1 = 1;
    private int date2 = 2;
    public static int date3 = 3;

    //非静态内部类
     class InterClass{
        public  int date4 = 4;
        private int date5 = 5;
        //非静态内部类 需定义静态常量
        //外部类加载时,不会加载非静态内部类
        //常量是在编译时就确定的
        public static final int date6 = 6;
        //非静态内部类
        public void func(){
            System.out.println("InterClass->func");
            OuterClass2 outerClass2 = new OuterClass2();
            // 内部类 不能调用外部类非静态 成员变量
            System.out.println(outerClass2.date1);
            System.out.println(outerClass2.date2);
            System.out.println(date3);
            System.out.println(date4);
            System.out.println(date5);
            System.out.println(date6);
        }
    }
    //外部类
    public void func2(){
        System.out.println("OuterClass2->func");
        //外部类 不能调用内部类非静态 成员变量
        InterClass InterClass = new InterClass();
        System.out.println(date1);
        System.out.println(date2);
        System.out.println(date3);
        System.out.println(InterClass.date4);
        System.out.println(InterClass.date5);
        //外部类 可以直接调用 内部类的静态成员
        System.out.println(InterClass.date6);
    }
}

1. 非静态内部类 不能定义静态成员变量 和 静态方法;

因为static类型的属性和方法,在类加载的时候就会存在于内存中,但非静态内部类不随外部类加载,只有在外部类实例化是加载;

2. 可以为变量 加上final 修饰为常量,常量是编译时的阶段确定的

方法加上 final 表示此方法就一条,不能被重写

实例化 非静态内部类: 非静态内部类依赖于外部类

想访问非静态内部类 的成员,需先实例化外部类

public class Test2 {

    public static void main(String[] args) {
        System.out.println(OuterClass2.InterClass.date6);
    }
    public static void main1(String[] args) {
        //想访问非静态内部类 的成员,需先实例化外部类
        //1.这种写法不太好
        //OuterClass2.InterClass interClass = new OuterClass2().new InterClass();
        //2.先实例化 外部类 在实例化内部类
        OuterClass2 outerClass2 = new OuterClass2();
        OuterClass2.InterClass interClass = outerClass2.new InterClass();
        interClass.func();

    }
}

注意:

  1. 外部类中的任何成员都可以在非静态内部类方法中直接访问
  2. 非静态内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束
  3. 非静态内部类对象必须在先有外部类对象前提下才能创建
  4. 非静态内部类的非静态方法中包含了一个指向外部类对象的引用(两个 this,同名优先指向自己,访问外部 需 外部类名.this.同名成员)
  5. 外部类中,不能直接访问非静态内部类中的成员,如果要访问必须先要创建内部类的对象
class OuterClass3{
    public int date = 1 ;
    class InterClass2{
        public int date = 11111;
        public void func(){
            System.out.println("interClass2->func()");
            System.out.println(this.date);  //就近原则
            System.out.println(OuterClass3.this.date);
        }
    }
}
public class Test3 {
    public static void main(String[] args) {
        OuterClass3 outerClass3 = new OuterClass3();
        OuterClass3.InterClass2 interClass = outerClass3.new InterClass2();
        interClass.func();  
    }
}
// interClass2->func()
// 11111
// 1

8.3 匿名内部类

匿名内部类 直接调用 相当与无名,只能用一次

interface ITest{
    void func();
}

public class Test4 {
    public static void main(String[] args) {
        //匿名内部类
        new ITest(){
            @Override
            public void func() {
                System.out.println("匿名内部类");
            }
        }.func();   //直接调用
    }
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值