[Java]类和对象

一、 类与对象的基本概念

首先我们先来通过一个例子了解面向对象和面向过程的区别。

如果我们要洗衣服,我们有两种办法,一种是亲自动手洗:接水、倒洗衣粉、清洗、揉搓、清洗最后拧干再晾衣服。还有一种办法是直接把衣服放进洗衣机中,放入洗衣粉等洗衣机洗,最后我们只需将衣服拿出来晾就可以了。这就是一个典型的面向过程与面向对象的区别,前者注重过程,后者注重对象。

面向过程注重的是过程,在整个过程中所涉及的行为,就是功能。 面向对象注重的是对象,也就是参与过程所涉及到的主体。是通过逻辑将一个个功能实现连接起来

在java中,一切皆是对象,一切都围绕着对象进行,找对象,建对象,用对象,并维护对象之间的关系。 类:把具有相同属性和行为的一类对象抽象为类。类是抽象概念,如人类、犬类等,无法具体到每个实体。

对象:某个类的一个实体,当有了对象后,这些属性便有了属性值,行为也就有了相应的意义。

类是描述某一对象的统称,对象则是这个类中的一个实例,有了类之后就能产生具体的对象,一个类可以产生多个对象。

二、类和对象的创建

  1. 类的创建方法

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

<class_name> <对象名> = new <class_name>();

class为定义类的关键字,class_name为类名,{}中为类的主体。

class Person{
    public int age;//成员变量
    public String name;
    public String sex;
    public void eat(){//成员方法
        System.out.println("吃饭");
    }
    public void sleep(){
        System.out.println("睡觉");
    }
}
  1. 对象的创建方法

类名称 引用名称 = new 类名称()

Person person = new Person();

这个对象的引用 对象(在堆中储存)

(相当于给对象起了个名字)(所有类的对象都是引用数据类型)

Person person = new Person();//通过new实例化对象
person.eat();//调用成员方法需要通过对对象的引用
person.sleep();

注意事项:

  1. 在Java中一个源文件(*.java)只可以存在一个主类(public class)

  1. 类的命名规则:使用有意义的大驼峰单词命名法,每个单词的首字母都要大写

  1. 类中定义的成员变量都有默认值(数字类型 -> 0,boolean -> false,引用类型 -> null

  1. 关于引用数据类型的特殊值 null:null在Java中表示“空引用”,即只有名字,没有任何对内存中的地址,如果直接使用值为null的引用,去操作(使用.操作符)任何属性或者方法(成员变量、成员方法),都会报错。 如:空指针异常

在定义局部变量的时候必须要初始化,只有成员变量可以不用初始化。

三、static关键字

  1. 修饰属性(修饰类,修饰方法等)

当一个实例变量被static修饰后,它就开始表示类的属性,该类的所有对象共享此属性,且对象的属性值都是相同的,实例变量的属性被修饰后存放在JVM区。

当一个实例变量被static修饰后,不能通过引用对象来访问,只能通过类变量来访问

class TestDemo{
    public int a;
    public static int count;
    
    public static void change() {
        count = 100;
        //a = 10; error 不可以访问非静态数据成员
   }
}
public class Main{
    public static void main(String[] args) {
        TestDemo.change();//无需创建实例对象 就可以调用
        System.out.println(TestDemo.count);   
   }
}

注意:

不能在方法中定义一个静态变量,因为方法定义的变量是局部变量,在栈中存储,而静态变量则是在方法区中存储。若要在方法中定义一个static变量就会产生矛盾,因为一个变量不可能既在栈中存储,又在方法区中存储。

静态方法不能直接使用非静态数据成员或调用非静态方法(非静态数据成员和方法都是和实例相关的). this和super两个关键字不能在静态上下文中使用(this 是当前实例的引用, super是当前实例父类实例的引用, 也 是和当前实例相关).

  1. static修饰方法(类方法、工具方法)

static修饰的方法通过类名称直接访问方法,没有对象也可以访问。

class TestDemo{
    public int a;
    public static int count;
    
    public static void change() {
        count = 100;
        //a = 10; error 不可以访问非静态数据成员
   }
}

静态方法可以通过类名称直接访问,此类中没有对象也可以访问;成员方法和成员变量必须要通过类中的对象来访问。没有对象的方法去调用必须通过对象访问的变量和方法,二者之间矛盾。

class Person {
 public String name = "张三";
 public int age = 18;
}
class Test {
    public static void main(String[] args) {
        Person person = new Person();//必须使用引用对象来调用成员变量
        System.out.println("我叫" + person.name + ", 今年" + person.age + "岁");
   }
}

成员方法可以访问静态变量和静态方法,必须通过对象访问的方法去调用不需要对象就可以访问的变量和方法,逻辑通过static方法只能调用静态变量和静态方法等,static家族的成员可以相互调用(都属于静态域)

static String country= "中国";
void print(){
    static String country= "韩国";
}

四、面向对象的封装性

  1. private实现封装

private/ public 这两个关键字表示 "访问权限控制" . 被 public 修饰的成员变量或者成员方法, 可以直接被类的调用者使用. 被 private 修饰的成员变量或者成员方法, 不能被类的调用者使用.
class Person {
 public String name = "张三";
 public int age = 18;
}
class Test {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println("我叫" + person.name + ", 今年" + person.age + "岁");
   }
}

这样的代码导致类的使用者(main方法的代码)必须要了解 Person 类内部的实现, 才能够使用这个类. 学习成本较 高 一旦类的实现者修改了代码(例如把 name 改成 myName), 那么类的使用者就需要大规模的修改自己的代码, 维 护成本较高.

class Person { 
 private String name = "张三"; 
 private int age = 18; 
 
 public void show() { 
 System.out.println("我叫" + name + ", 今年" + age + "岁"); 
 } 
} 
class Test { 
 public static void main(String[] args) { 
 Person person = new Person(); 
 person.show(); 
 } 
} 

通过将方法封装成一个show方法,外部人员便可以直接调用show方法而不用关心内部是如何实现show方法的,大大提高了代码效率。

五、构造方法

1、构造方法:构造方法是类中非常特殊的一类方法,使用关键字new 实例化对象时实际上调用的就是该类的构造方法。

2.构造方法的作用就是产生对象

3.使用new关键字产生一个对象时,大致分为以下两步:

(1)为对象在堆中分配空间(空间大小由该类中成员变量的属性决定)

(2)调用对象的构造方法为对象成员变量赋值(当构造方法调用结束后,该对象初始化完成)

语法规则 1.方法名称必须与类名称相同 2.构造方法没有返回值类型声明 3.每一个类中一定至少存在一个构造方法(没有明确定义,则系统自动生成一个无参构造)

如果编译器中已经存在了有参构造,那么系统将不再自动生成无参构造。并且构造方法也支持重载。

class Person { 
 
     private String name;//实例成员变量
     private int age; 
     private String sex; 
 //默认构造函数 构造对象 
     public Person() { 
         this.name = "caocao"; 
         this.age = 10; 
         this.sex = "男"; 
 } 
 //带有3个参数的构造函数
     public Person(String name,int age,String sex) { 
         this.name = name; 
         this.age = age; 
         this.sex = sex; 
} 
     public void show(){ 
         System.out.println("name: "+name+" age: "+age+" sex: "+sex); 
 } 
 
} 
public class Main{ 
     public static void main(String[] args) { 
     Person p1 = new Person();//调用不带参数的构造函数 如果程序没有提供会调用不带参数的构造函数
     p1.show(); 
     Person p2 = new Person("zhangfei",80,"男");//调用带有3个参数的构造函数
     p2.show(); 
     } 
} 

注意:不能用一个实例化对象去调用它的构造方法,构造方法本身就在产生实例化对象,如果实例化对象调用构造方法就变成了鸡生蛋蛋生鸡问题。

六、this关键字

this表示当前对象引用(注意不是当前对象). 可以借助 this 来访问对象的字段和方法.

class Person { 
     private String name;//实例成员变量
     private int age; 
     private String sex; 
 
     //默认构造函数 构造对象
     public Person() { 
     //this调用构造函数
     this("bit", 12, "man");//必须放在第一行进行显示
 } 
 
     //这两个构造函数之间的关系为重载。
     public Person(String name,int age,String sex) { 
     this.name = name; 
     this.age = age; 
     this.sex = sex; 
 } 
 public void show() { 
     System.out.println("name: "+name+" age: "+age+" sex: "+sex); 
 } 
} 
public class Main{ 
     public static void main(String[] args) { 
     Person person = new Person();//调用不带参数的构造函数
     person.show(); 
     } 
} 
// 执行结果
name: bit age: 12 sex: man 

为什么通过构造方法给成员变量初始化了,但输出结果仍是默认值?

形参名称与成员变量名称相同。程序设计理念:就近匹配原则,编译器会找最近的相同名称的变量在哪

只有使用this关键字才可以打破就进匹配原则并从类中寻找匹配的变量。

 public Person(String name,int age,String sex){
      this.name = name;
       this.age = age;
       this.sex = sex;
    }

注意:

1.this.属性-》访问当前对象的属性

2.this()-》调用当前对象的构造方法

  1. 必须放在当前的构造方法的第一行

  1. 调用不能形成环的调用

  1. 必须放到构造方法里面

3.this.func();调用当前对象的成员方法

七、代码块

代码块:指的是使用{ }括起来的一段代码,称为代码块。根据定义的代码块的位置以及关键字的不同分为以下四种代码块。(同步代码块先不提及)

(一)普通代码块

定义在方法中,使用{ }括起来的一段代码。

  public static void main(String[] args) {
 
        //普通代码块
 
    }

(二)成员代码块

定义在类中,不加任何修饰符的代码块,又称构造块。优先于构造方法执行,有几个对象产生就调用几次构造块。

public class Test {
    public static void main(String[] args) {
        Student student1 = new Student();
        Student student2 = new Student();
    }
}
class Student{
    String name;
    {
        //构造块
        System.out.println("111");
    }
    public Student(){
        System.out.println("222");
    }
}

(三)静态代码块

使用static定义的代码块。一般用于初始化静态成员属性。

class Person{
private String name;//实例成员变量
 private int age; 
 private String sex; 
 private static int count = 0;//静态成员变量 由类共享数据 方法区
 
 public Person(){ 
 System.out.println("I am Person init()!"); 
 } 
 
 //实例代码块
 { 
 this.name = "bit"; 
 this.age = 12; 
 this.sex = "man"; 
 System.out.println("I am instance init()!"); 
 } 
 
 //静态代码块
 static { 
 count = 10;//只能访问静态数据成员 
 System.out.println("I am static init()!"); 
 } 
 
 public void show(){ 
 System.out.println("name: "+name+" age: "+age+" sex: "+sex); 
 } 
 
} 
public class Main { 
 public static void main(String[] args) { 
 Person p1 = new Person(); 
 Person p2 = new Person();//静态代码块是否还会被执行?
 } 
}

注意事项 : 静态代码块不管生成多少个对象,其只会执行一次,且是最先执行的静态代码块执行完毕后, 实例代码块(构造块)执行,再然后是构造函数执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值