首页 > 编程语言 >JAVA基础-类的成员

JAVA基础-类的成员

时间:2024-02-19 10:48:04浏览次数:21  
标签:JAVA 子类 成员 基础 System println 父类 public out

1. 类的成员-属性

属性这里就是成员变量,也叫成员变量,直接定义在类中的。

  1. 在方法体外声明的变量称之为成员变量
    1. 实例变量(不以static修饰)
    2. 类变量(以static修饰)
  2. 在方法体内部声明的变量称之为局部变量
    1. 形参(方法、构造器中定义的变量)
    2. 方法局部变量(在方法体内定义)
    3. 代码块变量(在代码块内定义)

成员变量与局部变量比较:

就近原则:
  当成员变量名与局部变量名一致时,若使用这个名字,使用的是离这个调用位置最近的变量(如果局部变量离的近就用局部变量,如果成员变量离得近,就用成员变量)。谁离我近,我就用谁。成员变量也可以用 this. 或类名(静态成员变量)来区分。

2. 类的成员-方法

1. 方法修饰符

private、缺省、protected、public

2. 方法重载

一个类中可以存在一个以上同名方法,只要它们的参数个数或者参数类型不同即可。

特点:
1.方法名相同
2.方法的参数类型,参数个不一样
3.方法的返回类型可以不相同
4.方法的修饰符可以不相同

3. 方法重写

在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的重置、覆盖。

特点:
1.子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表
2.子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型
3.子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限
4.子类不能重写父类中声明为private权限的方法
5.子类方法抛出的异常不能大于父类被重写方法的异常

注意:静态方法可以继承,但不能被重写,体现在 override 不能使用

public class PersonDemo {
    public static void main(String[] args) {
        Asia.nums();
        China.nums();
        Japan.nums();
    }
}
class Asia{
    public static void nums(){
        System.out.println("父类静态方法");
    }
}
class China extends Asia{
    public static void nums(){
        System.out.println("亚洲有9个人");
    }
}
class Japan extends Asia{
}

4. 形参和实参

形参:方法声明时的参数
实参:方法调用时实际传给形参的参数值

5. 值传递和引用传递

值传递:传递对象的一个副本,即使副本被改变,也不会影响源对象,因为值传递的时候,实际上是将实参的值复制一份给形参。
引用传递:传递的并不是实际的对象,而是对象的引用,外部对引用对象的改变也会反映到源对象上,因为引用传递的时候,实际上是将实参的地址值复制一份给形参。

1. 基本类型

由于原始内容和副本都是存储实际值,并且是在不同栈区,因此形参的操作,不影响原始内容。

2. 引用类型

引用类型分为两种情况:

  1. 一种是形参和实参保持指向同一个对象地址,则形参的操作,会影响实参指向的对象的内容。
private static void changePerson(Person person){
        person.setAge(19);
        person.setName("李四");
    }
  1. 一种是形参被改动指向新的对象地址(如重新赋值引用),则形参的操作,不会影响实参指向的对象的内容。
private static void changePerson1(Person person){
        person = new Person();
        person.setName("申公豹");
    }

3. String

String 类型比较特殊,虽然是引用类型,但是 String 类型是不可变的,所以不会影响原有的值。

3. 类的成员-构造器

定义:与类同名、不具有返回值,不能有return语句
作用:初识化对象、为成员属性赋值

特点:
1.Java 语言中,每个类都至少有一个 构造器
2.默认构造器的修饰符与所属类的修饰符一致
3.一旦 显式定义了 构造器,则系统不再提供默认构造器
4.一个类可以创建多个重载的构造器
5.父类的构造器不可被子类继承,子类构造方法,默认第一句调用父类无参构造,除非显式调用父类其他构造方法。

4. 类的成员-代码块

用大括号包括其来的一段代码,可以对类或者对象进行初始化操作。分为静态代码块和动态代码块

class CodeBlockDemo {
    {
        System.out.println("普通代码块");
    }
    {
        System.out.println("普通代码块1");
    }
    static{
        System.out.println("静态代码块");
    }
    static{
        System.out.println("静态代码块1");
    }
}

1. 静态代码块

  1. 可以有输出语句。
  2. 可以对类的属性、类的声明进行初始化操作。
  3. 不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。
  4. 若有多个静态的代码块,那么按照从上到下的顺序依次执行。
  5. 静态代码块的执行要先于非静态代码块。
  6. 静态代码块随着 类的加载 而加载,且只执行一次。

2. 非静态代码块

  1. 可以有输出语句。
  2. 可以对类的属性、类的声明进行初始化操作。
  3. 除了调用非静态的结构外,还可以调用静态的变量或方法。
  4. 若有多个非静态的代码块,那么按照从上到下的顺序依次执行。
  5. 每次创建对象的时候,都会执行一次。且先于构造器执行。

3. 成员执行顺序

属性赋值、构造方法赋值、代码块赋值、方法赋值之间执行顺序如何?

//同时在属性上,构造方法,代码块中对属性进行赋值。
public class CodeBlockDemo {
    private String name = "张三";
    {
        System.out.println("普通代码块修改前:" + name);
        name = "李四";
        System.out.println("普通代码块修改后:" + name);
    }

    public CodeBlockDemo(){
        System.out.println("构造方法修改前:" + name);
        name = "王五";
        System.out.println("构造方法修改后:" + name);
    }
    
    public String getName() {
        return name;
    }

    public static void main(String[] args) {
        CodeBlockDemo codeBlockDemo = new CodeBlockDemo();
        System.out.println(codeBlockDemo.getName());
    }
}

当执行后发现:
由此发现执行顺序:属性赋值 > 代码块 > 构造方法,普通方法需要调用,肯定排最后,后面赋值会覆盖前面的。

5. 类的成员-内部类

1. 内部类定义

  1. 我们把在一个类里面定义的类称为内部类(InnerClass)或嵌套类,把外面定义的类称为外部类(OutClass)或宿主类。它与普通外部类最大的不同,在于其实例对象不能单独存在,必须依附于一个外部类的实例对象
  2. 内部类可以很好地实现隐藏,一般的非内部类是不允许有private 与 protected权限的,但内部类却可以,而且内部类还拥有外部类中所有元素的访问权限。
  3. 内部类分为四种,成员内部类,静态内部类,局部内部类,匿名内部类

2. 成员内部类

成员内部类就是指没有被static修饰的内部类,也可以称为非静态内部类

public class OuterClassDemo {
    /**
     * 成员内部类
     */
    class memberInnerClass{
    }
}

语法:
如果是在外部类中,创建成员内部类对象的基本语法格式如下:

内部类 对象名 = new 内部类();

如果是在外部的其他类中,或者是在外部类的静态方法中,创建成员内部类对象的基本语法格式如下:

内部类 对象名 = new 外部类().new 内部类();

3. 静态内部类

静态内部类和成员内部类的定义类似,但要使用static修饰,所以称为静态内部类(Static Nested Class)。

静态内部类和成员内部类有很大的不同,它不再依附于Outer的实例,而是一个完全独立的类,因此无法引用Outer.this的方式调用。但它可以访问Outer类的private静态字段和静态方法,如果我们把静态内部类移到Outer类之外,就失去了访问private的权限。

public class OuterClassDemo {
    /**
     * 静态内部类
     * */
    static class staticInnerClass{

    }
}

语法:
创建静态内部类对象的基本语法格式如下:
内部类 对象名 = new 外部类.内部类();

4. 局部内部类

指在方法中定义的类,参考局部变量,无法静态,只能在方法内部使用。

public class OuterClassDemo {
    /**
     * 局部内部类
     * */
    public void method(){
        class methodInnerClass{

        }
    }
}

5. 匿名内部类

匿名内部类就是指没有类名的内部类,必须在创建时使用 new 语句来声明。匿名内部类不能在Outer Class外部类中定义,而是要在某个方法的内部,通过匿名类(Anonymous Class)的形式来定义。匿名内部类本身就是一个对象。

通常情况下,如果一个方法的参数是接口类型,且该接口只需要实现一次,那么我们就可以通过匿名内部类的形式来进行定义。另外如果该接口的实现每次都不同,也可以使用匿名内部类的形式进行定义。我们也可以把这种定义形式叫做“接口回调”。匿名内部类的代码格式使得代码更加简洁、紧凑,模块化程度也更高。

public class OuterClassDemo {
    /**
     * 匿名内部类
     * */
    public void method1(){
        new Supplier<String>() {
            @Override
            public String get() {
                return null;
            }
        }.get();
    }
}

● 匿名内部类本身就是一个对象;

● 一般在匿名内部类中不会定义属性和方法,因为没有意义;

● 匿名内部类的父类一般都是抽象类或者是接口;

实现匿名内部类:
● 继承一个类,重写其方法;
● 实现一个或多个接口,并实现其方法。

new <类或接口>(){ 重写类或接口的方法 }

6. 关于继承

1. 成员是否可以继承

1. 属性

Sample:

public class ExtendsDemo {
    public static void main(String[] args) {
        Son son = new Son();
        //查看属性值
        son.getParentField();
        //通过父类引用修改属性值
        son.changeParentField();
        //查看属性值
        son.getParentField();
    }
}

class Father{
    private String name;
    public int age;
    static int step;

    public StringBuffer str;

    public Father(){
        this.age = 10;
        step = 100;
        str = new StringBuffer("测试");
    }
}

class Son extends Father{

    /**
     * 调用子类构造方法,默认第一行是父类的无参构造,所以这里打印从父类继承的三个子类,是父类的构造方法赋的值,不奇怪。
     * 这个构造方法中还通过子类修改了从父类继承的几个属性。
     */
    public Son(){
        System.out.println(this.age); //10
        this.age = 11;
        System.out.println(Son.step); //100
        Son.step = 102;
        System.out.println(this.str); //测试
        this.str.append("子类的");
    }

    /**
     * 不管是使用 super 还是 this 调用属性,都是在子类构造方法中修改过的值,这说明父类的值也被修改了
     * */
    public void getParentField(){
        System.out.println("父:" + super.age);   //11
        System.out.println("子:" + this.age);    //11
        System.out.println("父:" + Father.step); //102
        System.out.println("子:" + Son.step);    //102
        System.out.println("父:" + super.str);   //测试子类的
        System.out.println("子:" + this.str);    //测试子类的
    }

    /**
     * 通过父类引用改变属性值
     * */
    public void changeParentField(){
        super.age  = 10;
        Father.step = 100;
        super.str.append( "父类的" );
    }
}

总结:

  • private 修饰的属性不能继承,其他权限符都可以。
  • static 属性和非 static 属性都可以被继承。
  • 在可以继承的属性中,父子类是共用的这个属性,通过子类或父类引用修改属性值,另一方也会修改。
  • 如果子类有跟父类一样的属性,那就各论各的,谁也不影响谁。

2. 构造器

Sample:

public class Class_1 {
    public static void main(String[] args) {
        new S_1();
        System.out.println("-------------");
        new S_1("");
        System.out.println("-------------");
        new S_1("", null);
    }
}

class F_1{
    private String name;

    public F_1(){
        System.out.println("父类无参构造");
    }
    public F_1(String name){
        this.name = name;
        System.out.println("父类有参构造");
    }
}

class S_1 extends F_1{
    //这里默认第一行调用父类无参构造
    public S_1(){
        System.out.println("子类有参构造");
    }
    //这里也是默认第一行调用父类无参构造
    public S_1(String name){
        System.out.println("子类有参构造");
    }
    //这里显式调用父类有参构造
    public S_1(String name, String name1){
        super(name);
        System.out.println("子类有俩参构造");
    }
}

总结:

  1. 构造方法无法被继承
  2. 子类的构造方法第一行会默认调用父类的无参构造,如果使用 super() 显式调用父类有参构造,则替换为调用的父类构造。同时这个只能第一行调用。用 this() 也是同样的效果。
  3. 父类如果没有无参构造,子类构造方法不处理的话,因为找不到父类的无参构造,会报错。

3. 代码块

Sample:


public class Class_2 {
    public static void main(String[] args) throws ClassNotFoundException {
        new S_2();
    }
}

class F_2{
    static String test;
    static {
        System.out.println("父类静态代码块");
    }
    {
        System.out.println("父类代码块");
    }
}

class S_2 extends F_2{

}

继承没继承也不知道,反正调用了。。

4. 方法

public class Class_3 {
    public static void main(String[] args) {
        S_3.method();
        new S_3().method1();
    }
}

class F_3{
    public void method1(){
        System.out.println("父类方法 method1");
    }
    public static void method(){
        System.out.println("父类静态方法");
    }
}

class S_3 extends F_3{
    public static void method(){
        System.out.println("子类静态方法");
    }
}

总结:

  1. 对于 private 方法,肯定是不能继承的,其他权限修饰符是可以的,然后就有了重写一说
  2. 对于静态方法,比较特殊,可以认定为可以继承,因为可以直接通过子类名称去调用。但是重写的时候,可以方法签名跟父类一摸一样,但是不能用 @override,传说中的可以 继承但不能重写,感觉跟非静态方法,就差个 @override

5. 内部类

懒得研究,参考属性吧。。

2. 父子类属性重名问题

首先声明,开发过程中不建议这么干。如果这么干了,那么如何区分呢?

public class DogDemo {
    public static void main(String[] args) {
        BigDog bigDog = new BigDog();
        bigDog.getName();  //李四
        bigDog.findName(); //张三
    }
}


class Dog{
    String name;
    public Dog(){
        this.name = "张三";
    }

    public void getName() {
        System.out.println(name);
    }

    public void findName(){
        System.out.println(name);
    }
}

class BigDog extends Dog{
    String name;
    public BigDog(){
        this.name = "李四";
    }

    @Override
    public void getName() {
        System.out.println(name);;
    }
}

由于 getName() 在子类中重写,所以这里获取的指定是子类的 name 属性。这个地方应该类似于方法重写,属性也被子类覆盖了。而 findName() 由于没有重写,调用的是父类的方法,所以打印的也是父类的属性。

3. 对继承的理解

继承应该是这种结构,将父类整个放到子类中,当子类引用成员时,会先从子类内容中获取,获取不到再从父类中获取。

For Example:

public class Class_1 {
    public static void main(String[] args) {

        new S_1().getName();
    }
}
class F_1{
   String name = "父类";

    public String getName() {
        return name;
    }
}
class S_1 extends F_1{
   String name = "子类";
}

此时打印应该是 “子类”,因为子类没有 getName() 这个方法,所以去调用父类的 getName() 方法,而父类的 getName() 拿到的 name 属性自然是父类的。

标签:JAVA,子类,成员,基础,System,println,父类,public,out
From: https://www.cnblogs.com/cnff/p/17669533.html

相关文章

  • JAVA基础-内存与垃圾回收
    1,运行时数据区1,程序计数器线程私有。生命周期:生命周期与线程同步。作用:它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。特点:它是一块很小的内存空间,几乎可以忽略不记。也是运行速度最快的存储区域,唯一没有OutofMemory......
  • JAVA基础-IO
    1,IO概念IO通常表示计算机与外界数据的输入与输出。I/O流:IO流又叫输入输出流,输入和输出均是以内存作为参照物分类:1)按照流的方向以内存为参考物,往内存中去,叫做输入,从内存中出来,叫做输出。2)按照读取数据方式字节流,一次读取一个字节byte字符流,一次读取一个字符,具体几个......
  • JAVA基础-SPI
    1,什么是SPISPI全名ServiceProviderinterface,翻译过来就是“服务提供接口”,再说简单就是提供某一个服务的接口,提供给服务开发者或者服务生产商来进行实现。JavaSPI是JDK内置的一种动态加载扩展点的实现。这个机制在一般的业务代码中很少用到(个人接触到的业务没有用到过),但是......
  • JAVA基础-反射
    1,什么是反射?  Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类......
  • JAVA基础-泛型
    1,泛型概述泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型......
  • JAVA基础-序列化
    1,什么是序列化?Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程。2,序列化的使用场景永久性保存对象,保存对的字节序列到本地文件或者数据库中;通过序列化以字节流的形式对象在网络中进行传递和接收;通过序列化在进程间传递......
  • JAVA基础-Steam
    1,OptionalJava8中的Optional是一个可以包含或不可以包含非空值的容器对象。1.1,获取Optional的三个方法1.of(value)返回一个Optional,value不可以为null2.empty()返回一个空的Optional3.ofNullable(value)返回一个Optional,如果value为null,就是empty(),否......
  • JAVA基础-类加载过程
    1,类的加载1,类的加载过程2,加载阶段通过一个类的全限定名获取定义此类的二进制字节流将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口加载class文件的方式:从本......
  • JAVA基础-jdk8新特性
    Java8新特性:接口默认方法和静态方法JDK1.8打破了接口只提供了形式,而未提供任何具体实现这一限制,允许定义默认方法和静态方法。定义一个接口:packagecom.zgjt.design.defaults;importjava.util.function.Supplier;publicinterfaceAnimal{//接口默认方法,不必重......
  • Java开发的SRM供应商、在线询价、招投标采购一体化系统源码功能解析
    前言:随着全球化和信息化的发展,企业采购管理面临越来越多的挑战。传统的采购方式往往涉及到多个繁琐的步骤,包括供应商筛选、询价、招投标等,这些过程不仅耗时,而且容易出错。为了解决这些问题,供应商、询价、招投标一体化系统应运而生。该系统通过集成供应商管理、询价管理、招投标......