java:从类(class)的角度结构化总结变量,构造器,代码块,内部类及方法

前言

java是一门面向对象的语言,而对象是类的一个实例,有行为和状态。类是一个模板,它描述一类对象的行为和状态。所以本文将从一个类作为模板的角度,从结构上对类这个抽象概念进行分析描述。

模板图

说明:图中标红的属于类这个概念,由于匿名内部类,比较特殊(它与局部类很相似,不同的是它没有类名,如果某个局部类你只需要用一次,就可以采用局部内部类来定义它)所以在模板图中就不做展示,关于抽象类会在抽象方法中做说明。

1.成员变量

 1.1常量

         常量是指在程序的整个运行过程中值保持不变的量,常量值又称为字面常量,它是通过数据直接表示的。常量不同于常量值,它可以在程序中用符号来代替常量值使用,因此在使用前必须先定义。常量与变量类似也需要初始化,即在声明常量的同时要赋予一个初始值。常量一旦初始化就不可以被修改。

它的声明格式为:

final dataType variableName = value;

其中,final 是定义常量的关键字,dataType 指明常量的数据类型,variableName 是变量的名称,value 是初始值.,例如:

final  int i =5;

1.2静态常量

由final和static共同修饰的为静态常量。例如:

  final static int i=6;

静态常量和常量的区别:

static+final

  • 静态常量,编译期常量,编译时就确定值。
  • 放于方法区中的静态常量池。
  • 在编译阶段存入调用类的常量池中
  • 如果调用此常量的类不是定义常量的类,那么不会初始化定义常量的类,因为在编译阶段通过常量传播优化,已经将常量存到调用类的常量池中了

final

  • 常量,类加载时确定或者更靠后。
  • 当用final作用于类的成员变量时,成员变量(注意是类的成员变量,局部变量只需要保证在使用之前被初始化赋值即可)必须在定义时或者构造器中进行初始化赋值
  • 对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;
  • 如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。但是它指向的对象的内容是可变的

1.3.普通变量

在Java语言中,所有的变量在使用前必须声明。声明变量的基本格式如下:

type identifier [ = value][, identifier [= value] ...] ;

格式说明:type为Java数据类型。identifier是变量名。可以使用逗号隔开来声明多个同类型变量。如:

class Demo{
    int = 5;
}

 1.4静态成员变量

静态成员变量:也叫类变量,独立于方法之外的变量,用 static 修饰。

注意:

static修饰的成员变量属于类,不属于某个对象。即:多个对象访问或修改static修饰的成员变量时,其中一个对象将static成员变量进行了修改,其它的对象的static成员变量值跟着改变,即多个对象共享同一个static成员变量。

举例如下:创建狗类对象时,默认给值 为1,之后依次被修改。具体代码及运行结果如下

public class Demo {
    public static void main(String[] args) {
        //创建对象dog1
        Dog dog1 = new Dog();
        //调用test 方法
        dog1.test();
        //直接通过类名调用,并修改
        Dog.age = 2;
        System.out.println("类名调用修改后的age:"+Dog.age);
        //通过对象修改
        int age = dog1.age;
        age = 3;
        System.out.println("对象调用修改后的age:"+age);

    }
}
//创建狗类
class Dog{
   static int age = 1;
   public void test(){
       System.out.println("狗类中的age:"+age);
   }
}

输出结果为:

2.代码块

2.1静态代码块

static代码块指的是static{}包裹的代码块,且静态代码只执行一次,可以通过Class.forName("classPath")的方式唤醒代码的static代码块,但是也执行一次。

class Demo{
    //属性
   static int age;
    //静态代码块
    //静态信息初始化(预先加载资源)
    static {
        age = 1;
        System.out.println("静态代码块");
    }  
    
}

2.2构造代码块

使用{}包裹的代码区域,这里的代码区域特指位于class{}下面的而不是存在于其他type method(){}这类函数下面的代码区域

class Demo{
  
    {
        System.out.println("构造代码块");
    }
   
}

3.构造方法

构造方法,是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们,即构造函数的重载。

语法规则:

1.方法名必须与类名相同

2.无返回值类型,也不能用void修饰(有任何返回值类型的方法都不是构造方法)

3.可以指定参数,也可以不指定参数;分为有参构造方法和无参构造方法

构造方法的特点:

1.当没有指定构造方法时,系统会自动添加无参的构造方法。

2.构造方法可以重载:方法名相同,但参数不同的多个方法,调用时会自动根据不同的参数选择相应的方法。

3.构造方法是不被继承的

4.当我们手动的指定了构造方法时,无论是有参的还是无参的,系统都将不会再添加无参的构造方法。

例如,创建一个Person 类,添加age,name 属性,并添加无参构造及有参构造

class Person{
    //属性
    int age;
    String name;
    //无参构造
    public Person() {
    }
    //一个参数构造
    public Person(int age) {
        this.age = age;
    }
    //多个参数的构造
    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }
}

4.内部类

4.1成员内部类

首先内部类的概念是:在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。

成员内部类:在方法外类内定义类。(具体细节及注意事项等在下面代码中注明

/**
 * 成员内部类
 */
public class InnerDemo2 {

    public static void main(String[] args) {
        /**
         * 方法一
         */
        //创建成员内部类对象
        Outer2.Inner2 inner2 = new Outer2().in;
        //对象调用内部类方法
        inner2.n();
        /**
         * 方法二
         */
        Outer2.Inner2 inner21 = new Outer2().new Inner2();
        //对象调用内部类方法
        inner2.n();
    }
}

//外部类
class Outer2{
    //属性
    static int i =1;
    //非静态属性,可以通过对象调用
    Inner2 in = new Inner2();
    /**
     * 成员内部类:可以当成一个大的属性
     * 1.可以定义所有的非静态信息(属性,方法)及静态常量
     * 2.可以被4个访问权限修饰符修饰及final、abstract
     * 3.可以获取外部类所有信息
     */
    class Inner2{
        int x=2;
        static final int xx =3;
        //报错 static 不能修饰
        //static int xxx =4;
        public void n(){
            System.out.println(i);
            m();
        }
    }
    //方法
    public void m(){}
}

4.2静态内部类

静态内部类:成员内部类加上static(具体细节及注意事项等在下面代码中注明

/**
 *静态内部类
 */
public class InnerDemo3 {
    public static void main(String[] args) {
        //创建静态内部类对象
        Outer3.Inner3 inner3=new Outer3.Inner3();
        inner3.n();
    }
}

//外部类
class Outer3{
    //属性
    static int i=1;
    //静态内部类
    //可以定义所有的信息以及静态常量
    //可以进行继承和实现
    //可以被访问权限修饰符以及final/abstract
    //只能获取外部类的所有静态信息
    static class Inner3 extends Object implements Cloneable{
        static final int x=2;
        public void n(){
            System.out.println(i);
        }
    }
    //方法
    public void m(){}
}

5.成员方法

方法的定义:

  • 方法是类或对象的行为特征的抽象。
  • Java中的方法不能独立存在,所有的方法必须定义在类中。
  • 使用 “类名.方法” 或 “对象.方法” 的形式调用。
  • 语法格式:

    权限修饰符 返回值类型 方法名(参数类型 参数名) {

      // 方法体

      // 返回值

    }

5.1静态方法

静态方法:static修饰的方法,从属于类。最常见的main()方法就是一个静态方法

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

静态方法随着类的加载而加载到方法区的静态方法区里,与类同级也叫类方法,通过类名.形式来调用。静态方法存放在静态区里不会被赋予系统默认初始值,当静态方法被调用时会加载到栈中进行执行(类名.形式--参考如下代码)。

public class Demo {
    public static void main(String[] args) {
        //直接通过类名.形式来调用
       Dog.eat();
    }
}
//创建狗类
class Dog{
    static void eat(){
        System.out.println("狗吃东西");
    }
}

注意事项:

  • 静态方法可以重载
  • 静态方法不能重写
  • 静态信息(变量、方法。。)可以使用静态信息,但是不能直接使用非静态信息
  • 非静态信息可以直接使用静态信息以及非静态信息
  • this 是非静态的,静态方法里面不能直接使用

5.2普通方法

普通方法:没有static,final 等关键字修饰的方法

  • 可以进行方法的重载
  • 可以进行方法的重写
//创建狗类
class Dog{
   public void sleep(){
        System.out.println("狗在睡觉");
    }
}

5.3最终方法

最终方法:被 final 修饰的方法

注意事项:

  • 最终方法不能被重写
  • 最终方法可以重载
  • 最终类和非最终类都可以包含最终方法
public class demo {
    //编写最终方法add
  public final static int add(int a,int b) {
    return a+b;
  }
}

//此时会报错“cannot override the final method from demo”
//不能重写来自demo的最终方法
public class mydemo extends demo{
  public static int add(int a,int b) {
      return a+b;
    }
  public static void main(String[] args)
{
      int x=10;
      int y=2;
      System.out.println(add(x,y));
    }
}
//非最终类包含最终方法
class demo {
    public final static int add(int a,int b) {
        return a+b;
    }
    public static void main(String[] args)
    {
        int x=20;
        int y=5;
        System.out.println(x/y);
        System.out.println(add(x,y));
    }
}
//运行结果:
//4
//25

5.4抽象方法

抽象方法:被关键字abstract 修饰的方法

当父类中的某个方法被所有子类进行不同程度的重写,那么父类里的这个方法就没有实际意义,则舍弃掉方法体,加上 abstract 变成抽象方法(没有方法体---一定要重写)。

抽象类

抽象方法所在的类就是抽象类。如果普通类继承抽象类,那么需要重写所有的抽象方法,如果不想重写,则类需要修改为抽象类。

注意:

  • 抽象类里不一定含有抽象方法
  • 抽象类不能创建对象,否则能调用到抽象方法,就会出现问题(可以定义构造方法,但是不能创建对象)
  • 抽象类可以做属性初始化
  • 抽象方法支持重载(重载只和方法名和参数列表有关)
  • 抽象方法不可以被private/final/static,抽象方法一定需要重写
  • 抽象类不能被final 修饰,因为抽象方法一定需要重写,重写前提是继承,最终类没有子类就不行
  • 抽象类的目的主要是为了延展类继承结构
/**
 * 抽象类:Employee
 */
abstract class Employee
{
    //属性
    private String name;
    private String address;
    private int number;
    //抽象方法
    public abstract double computePay();

}

5.5方法内部类

方法内部类:方法内定义的类。

注意:

  • 方法内部类中可以定义所有的非静态信息以及静态常量
  • 方法内部类中可以进行正常的继承和实现
  • 方法内部类不能被访问权限修饰符来修饰,但是可以被final、abstrat 修饰
  • 方法内部类可以获取外部类所有的信息
  • 方法内部类只能获取本方法中的常量
  • 方法内部类创建对象需要在本方法中
package com.tedu.inner;

/**
 * 方法内部类
 */
public class InnerDemo1 {
    public static void main(String[] args) {
        //外部类对象调用m()方法,执行创建内部类对象的代码
        new Outer1().m();
    }
}
//外部类

/**
 * 类只能被public default 修饰
 */
 class Outer1{
    //属性
    int x = 1;
    //方法
    public void m(){
        /**
         * 1.jdk 1.8 开始默认底层加上final
         * 2.jdk1.7 及其以前需要强制加上final
         */
        int k = 10;
        //此处修改k=8 内部类System.out.println(k); 就会报错
        //k=8;
        //方法内部类
        /**
         * 1.可以定义所以非静态属性和方法以及[静态常量]
         * 2.可以进行正常的继承和实现
         * 3.不能被访问权限修饰符修饰,但是可以被final,abstract 修饰
         * 4.方法内部类,可以获取外部类所有的信息
         * 5.只能获取本方法中的常量信息
         */
        class Inner1 extends Object implements Cloneable{
            int y = 2;
            //静态属性和方法不行
            //静态区没有存储所以
            static final int yy=2;
            public void mn(){
                System.out.println(x);
                n();
                //只有拿本方法中的变量才会默认加上final,否则不加,比如上面执行k=8时,就
                //不会添加final
                System.out.println(k);
                //报错,k 默认是常量不能被改变
                //System.out.println(k=1);
            }

        }
        //在本方法中创建内部类实例
        Inner1 inner1 = new Inner1();
        inner1.mn();
    }
    public void n(){}
}
原创文章 3 获赞 2 访问量 128

猜你喜欢

转载自blog.csdn.net/qq_32224047/article/details/106174943