java类和对象的基础特性-2

简介: java类和对象的基础特性

java类和对象的基础特性-1

https://developer.aliyun.com/article/1515748


       4、局部变量

和c语言相比,java中的类的结构与c语言中的结构体类似,在java语言中,一个在类中、在方法外定义的变量称为成员变量,在类中定义的方法,称为成员方法,而在成员方法(外加普通方法)中定义的变量为局部变量


局部变量的有效范围是在当前代码块的,例如:有这样一段代码

public static void function(int[]arr){
        int i = arr.length;
        for (int j = 0; j < i - 1; j++) {
            for (int k = 0; k < j-1; k++) {
                if( arr[j]> arr[k]){
                    int tem = arr[j];
                    arr[j] = arr[k];
                    arr[k] = tem;
                }
            }
        }
    }


其中的i就为局部变量,j和k也是局部变量,只不过他们两个的作用范围都被限制在了for循环语句中,他们的作用范围如图:

其中的int[ ]  arr 其实也是一个局部变量,他的作用范围为整个方法的内部

注意:类中成员变量不不赋值的话都会有一个默认值,这在前面的已经提过,但是如果是局部变量在定义的时候没有赋值(初始化)的话就会编译报错。


        5、this关键字

在学习了局部变量的时候,结合private我们可以提出这样的一个问题,如果类中方法的传入的参数和我们要去修改的被private修饰的成员名一样的话会如何赋值,例如:在这个狗类中

class Dog {
    private String name;
    int age;
    public void dis(String name){
        name = name;
    }
    public void GetName(){
        System.out.println(name);
    }
}
 
class specialDog extends Dog {
    public void func() {
        System.out.println("the sepcial dog");
    }
}
public class Test{
    public static void main(String[] args) {
        Dog dog1 = new Dog();
        dog1.dis("修勾");
        dog1.GetName();
    }
}


我们修改dog1为继承了Dog的specialDog的对象,这里利用接口函数去修改他的name然后获取这个(打印)name:结果如下

null

显然是这个地方除了问题,有两个name,一个是Dog类中成员变量name,一个是Dog类中方法的局部变量name,编译器就默认name为局部变量中的类。


如果遇到这种情况该如何区分是局部变量还是成员变量中的变量呢?   在java语言中规定使用this关键字来代表本类的对象的引用,我们将上述代码中的   name  =   name  改为:


this.name   =   name  


编译器就会区分,原来前面这个name指的是这个类中的成员变量。

修改后的运行结果:

如果没有加this关键字,就相当于把局部变量的name赋值给自己,然后成员变量的name没有被初始化,给出的默认值为null,打印结果就为null。在后面还会讲到this的其他用法。


       3、类的构造方法


从我们上面的例子可以看出来,我们定义一个对象,初始化赋值过程都是在创建完对象之后赋值,那有没有一种办法可以在创建对象结束之前就可以赋值呢?答案是肯定的。


       在类中除了这种成员访问或成员方法接口等来修改之外,还存在一种特殊类型的方法,那就是构造方法。每当我们实例化一个对象的时候,就会自动调用构造方法,(如果没有自己手动写构造方法,就会自己调用一个内容为空的构造方法,即一个不带参数的构造方法)


构造方法有如下几个特点:

1、构造方法没有返回值


2、构造方法名称要与其类名相同

3、在定义构造方法的时候,构造方法没有返回值,如普通方法不同的是,构造方法不用在前面加上void返回类型的字样。


4、类中默认提供一个不带参数的构造方法


5、如果自己提供了一个构造方法,那么编译器默认不再提供不带参数的构造方法。

如果自己提供了一个不是不带参数的构造方法,那么当你企图用一个无参构造方法去实例化一个对象的时候就会报错,因为他在里面找不到不带参数的构造方法,此时编译报错。

其语法格式如下:

class A{
    public A(){
        ..... // 构造内容
    }
}

举例:

class Dog {
    private String name;
    int age;
    public Dog(String name,int age){
        this.name = name;
        this.age  = age;
        System.out.println("狗名为:"+this.name);
        System.out.println("狗龄为:"+this.age);
    }
}
public class Test{
    public static void main(String[] args) {
        Dog dog1 = new Dog("修勾",5);
    }
}


结果为:

事实上,this也可以调用类中的构造方法,看实例:

class Dog {
    private String name;
    int age;
    public Dog(String name){
        this.name = name;
        System.out.println(this.name);
    }
    public Dog(){
        this("this调用无参构造方法");
        System.out.println("无参构造方法");
    }
}
public class Test{
    public static void main(String[] args) {
        Dog dog1 = new Dog();
    }
}

其调用顺序为:

除了构造方法以外,更方便的也可以直接进行对成员变量的幅值,这样就修改了成员变量的初始值。后面仍然可以对其进行赋值操作。


同时,构造方法也支持重载,在传入不同的参数需要对应做出不同的反应的时候,这个时候就可以将构造方法重载。

        4、static:静态变量、常量、方法

       1、static关键字


我们知道,不同的对象有不同的属性,这些属性包括动态属性和静态属性(这里的静态属性不是值得静态static修饰的属性,而是类的成员变量)。但是我们在处理问题的时候,可能会遇到不同对象要使用同一个数据的情况,就比如设计一个球类和圆类,他们在计算的时候都会需要用到一个PI(π)常量,如果用常规方法在这两个类中都定义一个PI成员,系统就会将这两个不在同一个类的成员分配到不同的内存中造成空间浪费。为了解决这个问题,可以使用static关键字,将这个常量设置为静态的。用图表示为:


由static修饰的成员属于类所有,同时这个成员不再依赖于对象,可以直接使用这样的语法形式来访问这个static修饰的成员:

类名.被static修饰的成员

也可以使用对象.static成员的方法来使用,但是不推荐,因为对象. 的形式访问是面向对象的常用访问方法,在这里容易错误的将static成员看成非static成员。

static修饰的成员仍然受权限修饰符的限制。

注意:

静态方法中无法使用this关键字


this是在实例化一个对象的时候使用,然后静态成员或者方法是在类形成的时候就创建的,因此静态方法不能直接使用非静态方法。


       2、static修饰的代码块

       在使用任何被static修饰的变量的时候,或者是在使用某些方法之前,需要初始化static变量,为了除了这种情况,java提供了static修饰的代码块,在加载类的时候就执行,初始化这些变量,以达到这种需求:

class Dog {
    public static  String name;
    public  static int age;
    static{
        name = "xiaoli"
        age = 5
    }
}

static修饰的成员成为静态成员,被static修饰的语句或者语句块成为静态语句或者静态代码块。

在实例化一个对象的时候,所有静态代码块会首先依次执行完,在第二次创建对象的时候这个这些被static修饰的语句或者代码块不会再执行。

 

class Dog {
    public  String name;
    public  int age;
    static{
        System.out.println("静态代码块执行");
    }
    {
        System.out.println("实例代码块执行");
    }
    public Dog(String name,int age){
        System.out.println("构造代码块执行");
        this.name = name;
        this.age  = age;
        System.out.println("狗名为:"+this.name);
        System.out.println("狗龄为:"+this.age);
    }
}
public class Test{
    public static void main(String[] args) {
        Dog dog1 = new Dog("修勾",5);
        Dog dog2= new Dog("大狗",8);
    }
}


运行结果为:

 

可以看出来,静态代码块在构造方法之前执行,且只会执行一次,第二次创建对象的时候不会再执行。实例代码块在静态代码块之后,构造方法之前执行,但是实例代码块每次在创建对象的时候都会执行。

       3、面试题

为了让读者更好的理解静态方法的使用,请看例题:

下面关于静态方法说明正确的是

A.在静态方法中可用this来调用本类的类方法

B.在静态方法中调用本类的静态方法时可直接调用

C.在静态方法中只能调用本类中的静态方法

D.在静态方法中绝对不能调用实例方法

解析:


       静态方法中没有this关键词,因为静态方法是和类同时被加载的,而this是随着对象的创建存在的,静态比对象优先存在,因此选项A错误。也就是说,静态可以访问静态,但静态不能访问非静态而非静态可以访问静态。


在静态方法中可直接调用本类的静态方法,也可以通过类名.静态方法名的方式来调用其他类的静态方法,选项C错误。


D选项,静态方法不能直接调用实例方法和对象,但可以通过在静态方法中创建类的实例的方式间接调用


本次内容完........

目录
相关文章
|
12天前
|
Java
java代码优化:判断内聚到实体对象中和构造上下文对象传递参数
通过两个常见的java后端实例场景探讨代码优化,代码不是优化出来的,而是设计出来的,我们永远不可能有专门的时间去做代码优化,优化和设计在平时
29 15
|
2月前
|
Java 开发者
在 Java 中,一个类可以实现多个接口吗?
这是 Java 面向对象编程的一个重要特性,它提供了极大的灵活性和扩展性。
173 57
|
28天前
|
JSON Java Apache
Java基础-常用API-Object类
继承是面向对象编程的重要特性,允许从已有类派生新类。Java采用单继承机制,默认所有类继承自Object类。Object类提供了多个常用方法,如`clone()`用于复制对象,`equals()`判断对象是否相等,`hashCode()`计算哈希码,`toString()`返回对象的字符串表示,`wait()`、`notify()`和`notifyAll()`用于线程同步,`finalize()`在对象被垃圾回收时调用。掌握这些方法有助于更好地理解和使用Java中的对象行为。
|
1月前
|
存储 Java 开发者
什么是java的Compact Strings特性,什么情况下使用
Java 9引入了紧凑字符串特性,优化了字符串的内存使用。它通过将字符串从UTF-16字符数组改为字节数组存储,根据内容选择更节省内存的编码方式,通常能节省10%至15%的内存。
|
1月前
|
存储 Java 数据挖掘
Java 8 新特性之 Stream API:函数式编程风格的数据处理范式
Java 8 引入的 Stream API 提供了一种新的数据处理方式,支持函数式编程风格,能够高效、简洁地处理集合数据,实现过滤、映射、聚合等操作。
80 6
|
2月前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
76 8
|
2月前
|
存储 安全 Java
java.util的Collections类
Collections 类位于 java.util 包下,提供了许多有用的对象和方法,来简化java中集合的创建、处理和多线程管理。掌握此类将非常有助于提升开发效率和维护代码的简洁性,同时对于程序的稳定性和安全性有大有帮助。
89 17
|
2月前
|
分布式计算 Java API
Java 8引入了流处理和函数式编程两大新特性
Java 8引入了流处理和函数式编程两大新特性。流处理提供了一种声明式的数据处理方式,使代码更简洁易读;函数式编程通过Lambda表达式和函数式接口,简化了代码书写,提高了灵活性。此外,Java 8还引入了Optional类、新的日期时间API等,进一步增强了编程能力。这些新特性使开发者能够编写更高效、更清晰的代码。
43 4
|
2月前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
2月前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
149 4