JAVA基础篇:面向对象

一.类与对象的基本概念

类与对象是整个面向对象中最基础的组成单元。
类: 是抽象的概念集合,表示的是一个共性的产物,类之中定义的是属性和行为(方法);
对象: 对象是一种个性的表示,表示一个独立的个体,每个对象拥有自己独立的属性,依靠属性来区分不同对象。
可以用一句话来总结出类和对象的区别:类是对象的模板,对象是类的实例。类只有通过对象才可以使用,而在开发之中应该先产生类,之后再产生对象。类不能直接使用,对象是可以直接使用的。

二.类与对象的关系

什么是对象
面向对象程序设计(OOP)就是使用对象进行程序设计。对象(Object)代表现实世界中可以明确
标识的一个实体。
一个对象的状态(state,也称为特征(property)或者属性(arrtibute))是由具有当前值的
数据域来表示的。我们一般把对象的特有属性称之为成员变量。
一个对象的行为(behavior,也称为动作(action))是由方法定义的。调用对象的一个方法
就是要求对象完成一个动作。我们一般把对象的行为称之为成员函数。
什么是类
使用一个通用类来定义同一类型的对象。类是一个模板、蓝本或者说是合约,用来定义对象的数据
域是什么以及方法是做什么的。一个对象是类的一个实例。可以从一个类中创建多个实例。创建实例的
过程称为实例化。对象和实例经常是可以互换的。类和对象之间的关系类似于苹果派配方和苹果派之间
的关系。可以用一种配方做出任意多的苹果派来。

Java类使用变量定义数据域,使用方法定义动作。除此之外,类还提供了一种称为构造方法
(constructor)的特殊类型的方法,调用它可以创建一个新对象。构造方法本身是可以完成任何
动作的,但是设计构造方法是为了完成初始化动作。

三、类与对象的定义和使用

在Java中定义类,使用关键字class完成。语法如下:

class 类名称 {
属性 (变量) ;
行为 (方法) ;
}

例: 定义一个Person类

class Person {     // 类名称首字母大写
    String name ;
    int age ;
    public void tell() {        // 没有static
          System.out.println("姓名:" + name + ",年龄:" + age) ;
         }
}

类定义完成之后,肯定无法直接使用。如果要使用,必须依靠对象,那么由于类属于引用数据类型,所以对象的产生格式(两种格式)如下:

(1)格式一:声明并实例化对象

类名称 对象名称 = new 类名称 () ;

(2)格式二:先声明对象,然后实例化对象:

类名称 对象名称 = null ;
对象名称 = new 类名称 () ;

引用数据类型与基本数据类型最大的不同在于:引用数据类型需要内存的分配和使用。所以,关键字new的主要功能就是分配内存空间,也就是说,只要使用引用数据类型,就要使用关键字new来分配内存空间。

当一个实例化对象产生之后,可以按照如下的方式进行类的操作:
对象.属性: 表示调用类之中的属性;
对象.方法(): 表示调用类之中的方法。
例: 使用对象操作类

package com.openlab.classandobj;

class Person { 
    String name ;
    int age ;
    public void get() {
        System.out.println("姓名:" + name + ",年龄:" + age);
    }
}

public class TestDemo {
        public static void main(String args[]) {
            Person per = new Person() ;// 声明并实例化对象
            per.name = "张三" ;//操作属性内容
            per.age = 30 ;//操作属性内容
            per.get() ;//调用类中的get()方法
        }
}

运行结果:姓名:张三,年龄:30

四、private关键字,this关键字以及static关键字

1.private关键字的作用

在一个类中,一旦使用private进行修饰,那么本类中仍然可以随意访问;
但是超出本类范围就不能直接访问了。
间接访问private成员变量,就是定义一个Getter和Setter方法。
一般对成员属性的访问动作:修改器(设置 set),访问器(获取 get),因此对私有的变量访问的
方式可以提供对应的 setXxx或者getXxx的方法。

命名规则: 必须叫setXxx或者是getXxx,
对于Getter来说,不能有参数,返回值类型和成员变量对应。
对于Setter来说,不能有返回值,参数类型和成员变量对应。
代码示例:

public class Person {
    private String name; //姓名
    private int age; //年龄

    public void show(){
        System.out.println("我叫"+name+"年龄"+age);
    }

    //成员方法专门用于向age设置数据
    public void setAge(int num){
        if(num<100&&num>=0){
            age = num;
        } else {
            System.out.println("数据不合理!");
        }
    }

    //成员方法专门用于向name设置数据
    public void setName(String na){
        name = na;
    }

    //成员方法专门用于获取age的数值
    public int getAge(){
        return age;
    }

    //成员方法专门用于获取name的数值
    public String getName(){
        return name;
    }
}


2.this关键字的作用

this关键字主要有三个应用:
(1)this调用本类中的属性,也就是类中的成员变量;

(2)this调用本类中的其他方法;

(3)this调用本类中的其他构造方法,调用时要放在构造方法的首行。
应用一:引用成员变量

Public Class Student {
    String name; //定义一个成员变量name
    private void SetName(String name) { //定义一个参数(局部变量)name
        this.name=name; //将局部变量的值传递给成员变量
    }
}

应用二:调用类的构造方法

public class Student { //定义一个类,类的名字为student。
    public Student() { //定义一个方法,名字与类相同故为构造方法
        this(Hello!);
    }
    public Student(String name) { //定义一个带形式参数的构造方法
    }
}

应用三:返回对象的值

this关键字除了可以引用变量或者成员方法之外,还有一个重大的作用就是返回类的引用。

如在代码中,可以使用return this,来返回某个类的引用。此时这个this关键字就代表类的名称。

如代码在上面student类中,那么代码代表的含义就是return student。

可见,这个this关键字除了可以引用变量或者成员方法之外,还可以作为类的返回值,这才是this关键字最引人注意的地方。

3.static关键字的作用

1)修饰成员变量
在我们平时的使用当中,static最常用的功能就是修饰类的属性和方法,让他们成为类的成员属性和方法,我们通常将用static修饰的成员称为类成员或者静态成员,这句话挺起来有点奇怪,其实这是相对于对象的属性和方法来说的。
请看下面的例子:

public class Person {
    String name;
    int age;
    
    public String toString() {
        return "Name:" + name + ", Age:" + age;
    }
    
    public static void main(String[] args) {
        Person p1 = new Person();
        p1.name = "zhangsan";
        p1.age = 10;
        Person p2 = new Person();
        p2.name = "lisi";
        p2.age = 12;
        System.out.println(p1);
        System.out.println(p2);
    }
}

2.修饰成员方法
static的另一个作用,就是修饰成员方法。相比于修饰成员属性,修饰成员方法对于数据的存储上面并没有多大的变化,因为我们从上面可以看出,方法本来就是存放在类的定义当中的。static修饰成员方法最大的作用,就是可以使用"类名.方法名"的方式操作方法,避免了先要new出对象的繁琐和资源消耗,我们可能会经常在帮助类中看到它的使用:


public class Test {
 
    public static void print(Object o){
        System.out.println(o);
    }
    
    public static void main(String[] args) {
        Test .print("Hello world");
    }
}

3.静态块
当我们初始化static修饰的成员时,可以将他们统一放在一个以static开始,用花括号包裹起来的块状语句中:

class Book{
    public Book(String msg) {
        System.out.println(msg);
    }
}
 
public class Person {
 
    Book book1 = new Book("book1成员变量初始化");
    static Book book2;
    
    static {
        book2 = new Book("static成员book2成员变量初始化");
        book4 = new Book("static成员book4成员变量初始化");
    }
    
    public Person(String msg) {
        System.out.println(msg);
    }
    
    Book book3 = new Book("book3成员变量初始化");
    static Book book4;
    
    public static void funStatic() {
        System.out.println("static修饰的funStatic方法");
    }
    
    public static void main(String[] args) {
        Person.funStatic();
        System.out.println("****************");
        Person p1 = new Person("p1初始化");
    }
    /**Output
     * static成员book2成员变量初始化
     * static成员book4成员变量初始化
     * static修饰的funStatic方法
     * ***************
     * book1成员变量初始化
     * book3成员变量初始化
     * p1初始化
     *///~
}

4.静态导包
导包时添加static关键字,使被导入类中的静态方法/静态变量在当前类可直接调用,而无需使用类名加点的方式
导入语法:
import static 包名.类名.静态成员变量;
import static 包名.类名.静态成员方法;
import static 包名.类名.*;
未使用静态导入

public static void main(String[] args) {
    //调用math类中的random()方法生成随机数
    System.out.println(Math.random());
}

未使用静态导入时,需要通过类名Math加具体方法名random()来进行调用生成随机数
使用静态导入

import static java.lang.Math.random;

public class Demo {
    public static void main(String[] args) {
        //无需类名,直接通过random()方法生成随机数
        System.out.println(random());
    }
}

注意:
静态导入可减少代码输入量,但当两个不同的类中有命名相同的方法都使用静态导入时,仍然需要通过 类名 Math加 具体方法名 random()来进行调用,否则会报错!

总结:

static是java中非常重要的一个关键字,而且它的用法也很丰富,主要有四种用法:

  1. 用来修饰成员变量,将其变为类的成员,从而实现所有对象对于该成员的共享;
  2. 用来修饰成员方法,将其变为类方法,可以直接使用“类名.方法名”的方式调用,常用于工具类;
  3. 静态块用法,将多个类成员放在一起初始化,使得程序更加规整,其中理解对象的初始化过程非常关键;
  4. 静态导包用法,将类的方法直接导入到当前类中,从而直接使用“方法名”即可调用类方法,更加方便。

五、构造函数

构造函数的最大作用就是创建对象时完成初始化,当我们在new一个对象并传入参数的时候,会自动调用构造函数并完成参数的初始化
构造函数的规则:

构造函数与类同名
每个类可以有一个以上的构造函数
构造函数可以有0 个 、 1 个或多个参数
构造函数没有返回值
构造函数总是伴随着new操作一起调用
看一个例子:

public class Employee {


//    关键字 private 确保只有 Employee 类自身的方法能够访问这些实例域 , 而其他类的方法不能够读写这些域 。

//     可以用 public 标记实例域 , 但这是一种极为不提倡的做法
//public 數据域允许程序中的任何方法对其进行读取和修改 ,。 这就完全破坏了封装 。
//任何类的任何方法都可以修改 public 域 , 从我们的经验来看 , 某些代码将使用这种存取权限 , 而这并不我们所希
//望的 , 因此这里强烈建议将实例域标记为 private , ,

    private String name ;

    private double salary ;

    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", salary=" + salary +
                '}';
    }

    public static void main(String[] args) {


//        说明在我们创建Employee对象的时候,会自动调用构造函数完成初始化,

        Employee employee = new Employee("John",44545);

        System.out.println(employee);


    }
}


细节:

  • 如果你不写构造函数,程序会自动给你加上一个无参数无操作的构造函数(当然你看不见)
  • 如果你写了构造函数,则自定义构造函数会覆盖无参数构造函数
public class Employee_1 {

    @Override
    public String toString() {
        return "Employee_1{}";
    }

    public static void main(String[] args) {

//        没有显式提供构造函数
        
//        程序会自动给你加上一个无参数无操作的构造函数
        
        Employee_1 employee_1 = new Employee_1();

        System.out.println(employee_1);
    }
}


构造函数与普通函数的区别:

  1. 一般函数是用于定义对象应该具备的功能。而构造函数定义的是,对象在调用功能之前,在建立时,应该具备的一些内容。也就是对象的初始化内容。
  2. 构造函数是在对象建立时由JVM调用, 给对象初始化。一般函数是对象建立后,当对象调用该功能时才会执行。
  3. 普通函数可以使用对象多次调用,构造函数就在创建对象时调用。
  4. 构造函数的函数名要与类名一样,而普通的函数只要符合标识符的命名规则即可。
  5. 构造函数没有返回值类型。

初始化

为什么需要初始化?

java规定,变量没有初始化不能使用,全局变量也就是类的属性,java会在编译的时候,自动将他们初始化,所以可以不进行变量初始化的操作,但是(局部)变量必须初始化。

初始化就是在最开始定义成员变量时给它一个初始的值,为了防止程序运行时候出现未知的错误,或者bug,总之一句话,为了安全。

默认初始化

在Java中,一个类的数据成员(成员变量)如果没有指定初始化,那么Java会对其执行默认初始化

public class InitialValues {

    boolean t;
    char c;
    short s;
    int i;
    long l;
    float f;
    double d;
    String str;
    InitialValues reference;

    void printInitialValues() {
        System.out.printf("%-10s %-5s\n", "boolean:", t);
        System.out.printf("%-10s %-5s\n", "char:", c);
        System.out.printf("%-10s %-5s\n", "short:", s);
        System.out.printf("%-10s %-5s\n", "int:", i);
        System.out.printf("%-10s %-5s\n", "long:", l);
        System.out.printf("%-10s %-5s\n", "float:", f);
        System.out.printf("%-10s %-5s\n", "double:", d);
        System.out.printf("%-10s %-5s\n", "String:", str);
        System.out.printf("%-10s %-5s\n", "reference:", reference);
    }

    public static void main(String[] args) {
        InitialValues iv = new InitialValues();
        iv.printInitialValues();
    }

}

/*
输出内容
boolean:   false
char:           
short:     0    
int:       0    
long:      0    
float:     0.0  
double:    0.0  
String:    null 
reference: null 

*/

静态数据的初始化
初始化的顺序是:先静态对象,而后是“非静态”对象。

class Bowl{
    Bowl(int marker){
        System.out.println("Bowl("+marker+")");
    }
    void f1(int marker){
        System.out.println("f1("+marker+")");
    }
}


class Table{

    static Bowl bowl1=new Bowl(1);

    Table(){
        System.out.println("Table()");
        bowl2.f1(1);
    }


    void f2(int marker){
        System.out.println("f2("+marker+")");
    }


    static Bowl bowl2= new Bowl(2);
}


class Cupboard{

    Bowl bowl3=new Bowl(3);

    static Bowl bowl4=new Bowl(4);

    Cupboard(){
        System.out.println("Cupboard()");
        bowl4.f1(2);
    }


    void f3(int marker){
        System.out.println("f3("+marker+")");
    }


    static Bowl bowl5= new Bowl(5);


}

public class StaticInitialization {


//    要执行main(),必须加载StaticInitialization类,然后其静态域table和cupboard被初始化,这导致他们对应的类也被加载,并且由于它们都包含静态的Bowl对象,
//    因此Bowl随后也被加载。这样,在这个特殊的程序中的所有的类在main()开始之前就都被加载了。
//
//    首先从main()函数开始,加载StaticInitializaition类,然后对StaticInitializaition类中的静态域Table进行初始化,加载Table类,Table类中包含静态的Bowl对象,
//    接着加载Bowl类,加载Bowl类构造器创建bowl1对象,输出Bowl(1),加载Bowl类构造器创建bowl2对象,输出Bowl(2);同里创建cupboard对象。
//
//    需要注意的是,bowl3是非静态域,每次创建Cupboard对象都会创建一个Bowl对象。
    public static void main(String[] args) {
        System.out.println("Creating new Cupboard() in main");
        new Cupboard();
        System.out.println("Creating new Cupboard() in main");
        new Cupboard();
        table.f2(1);
        cupboard.f3(1);
    }

    static Table table = new Table();
    static Cupboard cupboard = new Cupboard();
}



非静态成员初始化
在一个类中,非静态成员的初始化,发生在任何方法(包括构造器)被调用之前。并且它们定义的顺序,决定了初始化的顺序。

class A{

    A(String s) {

        System.out.println(s);

    }
}

class B{

    A a1 = new A("a1");

    B() {

        System.out.println("B");
        A a2 = new A("a2");

    }

    A a3 = new A("a3");
    void f(){
        System.out.println("f---");
    }
    A a4 = new A("a4");
}

public class Initialization_1 {

    public static void main(String[] args) {

        B b = new B();

        b.f();

    }

}


静态块代码初始化
整个static { 静态代码块 } 可以看作是一个静态成员。当一个类需要执行静态初始化时,该类中的静态成员初始化和静态代码块,会按照先后定义的顺序执行。当然,这个流程也是就执行这一次。

class AA{

    public AA(String s) {

        System.out.println(s);
    }
}

class BB{
    AA a1 = new AA("a1");

    static AA a2 = new AA("a2");

    static AA a3,a4;

    static {

        System.out.println("______________");

        a3 = new AA("a3");

        a4 = new AA("a4");

        AA a5 = new AA("a5");

        System.out.println("++++++++++++");

    }

    static AA a6 = new AA("a6");

    AA a7 = new AA("a7");

    public BB() {

        System.out.println("BB");
    }
}
public class Initialization_3 {

    static BB b1 = new BB();

    public static void main(String[] args) {

        new BB();

    }


}


非静态代码初始化
非静态代码块,可以看作一个非静态成员。涉及非静态初始化,也会执行它。和普通的非静态成员初始化一样,它的执行也发生在构造器调用之前,并且每当创建对象之前都会调用。


class AA{

    public AA(String s) {

        System.out.println(s);
    }
}

class BB{
    AA a1 = new AA("a1");

    static AA a2 = new AA("a2");

    static AA a3,a4;

    {

        System.out.println("______________");

        a3 = new AA("a3");

        a4 = new AA("a4");

        AA a5 = new AA("a5");

        System.out.println("++++++++++++");

    }

    static AA a6 = new AA("a6");

    AA a7 = new AA("a7");

    public BB() {

        System.out.println("BB");
    }
}
public class Initialization_4 {

    static BB b1 = new BB();

    public static void main(String[] args) {

        new BB();

    }


}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值