Java面向对象(一)

一. 对象 VS 对象引用

  • 对象:类的一个实例化,存储在堆内存中
  • 对象引用:相当于c++中的指针,指向类的实例对象,存储在栈内存中
public class Person{
    char name;
    int age;
}
Person xiaoming = new Person();

说明:最后一行代码实际上等价于

Person xiaoming;
xiaoming = new Person();

new Person()就是在堆内存中创建了一个Person类的实例对象,xiaoming 即为一个对象引用,=不是赋值语句,而是地址传递,让栈内存中的对象引用指向堆内存中的实例对象

二. 对象作为参数传递

java本质上只有按值传递,无论是基本数据类型还是引用类型,当作为参数传递给一个方法时,两种类型都是按值传递的。

  • 在Java中,当对象作为参数传递时,实际上传递的是一份“ 引用的拷贝 ”,地址值。

    对比以下两例代码:

class Person{
    int age;
    char name;
    Person(int a){
        age = a;
    }
}
public class Test {
    public static void main(String[] args) {
        Person xiaoming = new Person(18);
        System.out.println(xiaoming.age); // 18
        changeAge(xiaoming,20);
        System.out.println(xiaoming.age); // 20
    }
    public static void changeAge(Person p,int a){
        p.age = a;
    }
}

说明:实参与形参指向同一个实例对象,堆内存中原对象的值改变

public class Test {
    public static void main(String[] args) {
        Person xiaoming = new Person(18);
        System.out.println(xiaoming.age); // 18
        changeAge(xiaoming,20);
        System.out.println(xiaoming.age);// 18
    }

    public static void changeAge(Person p,int a){
        p = new Person(a);
    }
}

说明:堆内存中原对象的值未改变,开辟了新的内存空间,实参与形参指向不同

三. 对象初始化顺序

class Person{
    int age;
    // int age = 15;
    Person(){
        System.out.println(age + " constructor");
    }
    Person(int a){
        System.out.println(age + " constructor");
        age = a;
    }
}
public class Test {
    public static void main(String[] args) {
        Person xiaoming = new Person();
        System.out.println(xiaoming.age);
        xiaoming = changeObj();
        System.out.println(xiaoming.age);
    }

    public static Person changeObj(){
        Person p = new Person(18);
        return p;
    }
}
/**
	0 constructor // 15 constructor
	0             // 15
	0 constructor // 15 constructor
	18            // 18
*/

结论

  1. 先对变量进行默认初始化,如果用户有自定义初值则直接执行
  2. 最后调用对应构造函数指定初值

四. static

static修饰的数据成员属于类的静态数据成员,存储在类内存区的公共存储单元,可以被任意类的实例对象访问

static变量

  1. static 修饰的变量称为类变量或全局变量或成员变量,在类被加载的时候成员变量即被初始化,与类关联,只要类存在,static变量就存在。非static修饰的成员变量是在对象new出来的时候划分存储空间,是与具体的对象绑定的,该成员变量仅为当前对象所拥有的。

  2. static修饰的变量在加载的时候先于main方法加载在内存中的数据共享区-------方法区,而非static的变量在加载的时候,是要创建变量才加载在堆内存中的。

  3. 一个static变量单独划分一块存储空间,不与具体的对象绑定在一起,该存储空间被类的各个对象所共享。static变量值在方法区加载一次,而非static在创建对象时会加载很多次。每次创建都会拷贝一份。

  4. 对象在引用成员变量是直接通过类名.变量名调用,对象在引用实例变量时只能通过对象名.变量名调用。

  5. 在类中调用成员变量时直接调用或者以类名.变量名方式调用,实例变量则用this或者直接调用。

static方法

  1. static修饰的方法也和static变量一样。先于main方法被加载到方法区,以便共享使用。

  2. 静态的static方法中不能使用this或者super关键字。非静态的方法是属于对象的,方法里可以用this和super。

  3. static方法可以用对象.方法名来调用,也可以用类名.方法名来调用。而非静态的方法只能创建对象后时调用。

  4. static方法是加载一次,被所有的对象所共享。而非静态方法是有多少个对象就拷贝多少次,每个对象只能调用自己的拷贝的方法。

  5. 对象调用非静态的方法时,不考虑线程安全性的问题,而调用静态方法时,要考虑安全性的问题。因为静态方法只有一份。而对象的方法是自己有自己的。

  6. 同一个类中,静态方法中只能访问类中的静态成员。而非静态方法可以访问静态成员(使用类名调用,或者创创建本类的对象调用)。

使用场景

  • 属于类的公有属性

  • 需要先初始化加载或者是被多次调用

    举例:

class Person{
    // Person 的公有属性
    static int age;
    static String name;
    Person(int a,String n){
        age = a;
        name = n;
    }
    // Person 的公有方法
    static void speak(){
        System.out.println("I am "+ name + " and I am "+ age + " years old.");
    }
}
public class Test {
    public static void main(String[] args) {
        Person xiaoming = new Person(18,"xiaoming");
        Person.speak(); // I am xiaoming and I am 18 years old.
        // xiaoming.speak();
    }
}

五. final

  • 修饰类、变量和方法,用于表示它修饰的类、方法和变量不可改变。

    • 修饰类,类不能被继承
    final class Person{
        int age = 18;
        static String name;
        Person(int a,String n){
            age = a;
            name = n;
        }
    }
    class Teacher extends  Person{} // 报错:java: 无法从最终Person进行继承
    
    • 修饰变量,变量为常量
    class Person{
        final int age = 18;
        static String name;
        Person(int a,String n){
            age = a; // 报错:java: 无法为最终变量age分配值
            name = n;
        }
    }
    
    • 修饰方法,方法不能被覆盖
    class Person{
        int age = 18;
        String name = "xiaoming";
        final public void speak(){
            System.out.println("I am "+ name + " and I am "+ age + " years old.");
        }
    }
    class Teacher extends  Person{
        public void speak(){ // 报错:java: Teacher中的speak()无法覆盖Person中的speak()
      					   //	      被覆盖的方法为final
            System.out.println("I am "+ name + " and I am "+ age + " years old.I am a teacher");
        }
    }
    

六. 数组

一维数组

数组声明
  • 声明的仅是引用变量,所以不可以在[]内指定数组大小
int[]  arr;             
String[]  example;  
Person[]  p;     
数组初始化
  1. 使用new关键字

类型标识符[] 数组名=new 类型标识符[数组长度];

int[] arr = new int[10];  
String[] example = new String[10];  
Person[] p = new Person[10];
  1. 直接在声明的时候进行定义及初始化
int[] a = {3,4,5,6};
String[] s = {"ab","bc","cd"};
Person[] p = {new Person("xiaoming"),new Person("xiaowang"),new Person("xiaoli")};
  1. 采用1和2结合的方法
int[] f4= new int[] { 1, 2, 3, 4}; 

二维数组

数组声明
int[][] arr;
数组初始化
  1. 使用new关键字

数组名=new 类型说明符[ 数组长度 ][];

数组名=new 类型说明符[ 数组长度 ][ 数组长度 ];

arr = new int[3][4];  
// 等价于
arr = new int[3][];
arr[0] = new int[4];
arr[1] = new int[4];
arr[2] = new int[4];
  1. 使用指定的初值对数组初始化
int[][] arr1={{3,-9,6},{8,0,1},{11,9,8}};
// 等价于
int[][] arr1=new int[3][];
arr1[0]= new int[]{3,-9, 6};
arr1[1]= new int[]{8,0,1};
arr1[2]= new int[]{11,9,8};

数据元素:基本 vs 引用

  • 基本数据类型默认值为0,引用数据类型默认值为null
  • 使用引用数据类型,每一个元素都是一个对象引用,指向另一块内存中的对象
public class Test {
    public static void main(String[] args) {
        
        int arr1[] = new int[10];
        for(int i=0; i < arr1.length; i++){
            System.out.printf("%d ",arr1[i]);
        }
        for(int i=0; i < arr1.length; i++){
            arr1[i] = i;
            System.out.printf("%d ",arr1[i]);
        }
        System.out.println();
        
        String arr2[] = new String[10];
        for(int i=0; i < arr2.length; i++){
            System.out.printf("%s ",arr2[i]);
        }
        for(int i=0; i < arr2.length; i++){
            arr2[i] = new String("ab"+ i);
            System.out.printf("%s ",arr2[i]);
        }
    }
}
/**
	0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 
	null null null null null null null null null null ab0 ab1 ab2 ab3 ab4 ab5 ab6 ab7 ab8 ab9  
*/

总结

​ 初步学习了Java是如何实现面向对象这一思想的,在学习过程中通过适当类比c++的语法帮助自己更好地掌握了Java类和对象的基础语法知识,但这只是开始,还需要更为深入的学习才能把握Java面向对象的精髓。

​ 在整理博客的过程中参考了一些资料以及许多他人优秀的文章,就不一一列举,在此表示感谢。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值