2021大数据学习之旅 JavaSE·面向对象(static、内部类、参数传递)


前言

系列文章比较适合非科班的同学, 由浅及深, 循序渐进, 从基础开始走上大数据之路

让我们一起努力, 达成目标, 实现理想

最后恳请留下你的小❤, 点赞给我一个小小的鼓励吧


一、static关键字

1.1 概述

static是静态修饰符,一般修饰成员。被static修饰的成员属于类,不属于单个这个类的某个对象。static修饰的成员被对象共享。static修饰的成员属于类,会影响每一个对象。被static修饰的成员又叫类成员。


1.2 static特点

  1. 被static修饰的成员变量属于类,不属于这个类的某个对象

    也就是说,多个对象在访问或修改static修饰的成员变量时,其中一个对象将static成员变量值进行了修改,其他对象中的static成员变量值跟着改变,即多个对象共享同一个static成员变量

public class Test {
    public static void main(String[] args) {
        Demo d1 = new Demo();
        Demo d2 = new Demo();

        // 静态变量一般是类名.变量名调用, 但是实例对象也是可以访问的
        d1.num = 20;

        System.out.println(d1.num);
        System.out.println(d2.num);
    }
}

class Demo{
    public static int num =10;
}

结果: 20; 20

  1. 静态内容是优先于对象存在,只能访问静态,不能使用this/super. 静态修饰的内容存于静态区。
class Demo {
	//成员变量
	public int num = 100;
	//静态方法
	public static void method(){
		//this.num; 不能使用this/super。
		//System.out.println(this.num);//报错
	}
}

  1. 同一个类中,静态成员只能访问静态成员
class Demo {
	//成员变量
	public int num = 100;
	//静态变量
	public static int count = 200;
	//静态方法
	public static void method(){
		//System.out.println(num); 静态方法中,只能访问静态成员变量或静态成员方法
		System.out.println(count);
	}
}

1.3 static使用格式

被static修饰的成员可以并且建议通过类名直接访问

类名.静态成员变量名
类名.静态成员方法名(参数)
对象名.静态成员变量名 ------不建议使用该方式,会出现警告
对象名.静态成员方法名(参数) ------不建议使用该方式,会出现警告;

举例:

class Demo {
	//静态变量
	public static int num = 100;
	//静态方法
	public static void method(){
		System.out.println("静态方法");
	}
}
class Test {
	public static void main(String[] args) {
		System.out.println(Demo.num);
		Demo.method();
	}
}

1.4 静态原理图解

static 修饰的内容:

  • 是随着类的加载而加载的,且只加载一次。
  • 存储于一块固定的内存区域(静态区),所以,可以直接被类名调用。
  • 它优先于对象存在,所以,可以被所有对象共享。

在这里插入图片描述


1.5 代码块

静态代码块:定义在成员位置,使用static修饰的代码块{ }。

  • 位置:类中方法外
  • 执行:随着类的加载而执行且执行一次,优先构造方法的执行。
  • 类的加载分为三步,加载,连接,初始化,准确的来说静态代码块只有在类的初始化的时候才会执行
  • 创建对象会初始化,访问静态变量会初始化,访问静态方法会初始化,创建子类对象,访问子类的静态成员会初始化
  • 访问静态常量不会初始化,

举例:

public class Person {
	private String name;
	private int age;
	
    //静态代码块
	static{
		System.out.println("静态代码块执行");
	}
}

局部代码块

  • 限制局部变量的作用范围
public static void main(String[] args){
    //int a = 20; 这是不可以的,这里的a在main方法都有用,和下面的a冲突了
    {
        int a= 10;
        System.out.println(a);
    }
}

成员代码块

  • 当创建对象的时候,就会执行,创建一个对象,就执行一个
  • 优先于构造方法

1.6 定义静态常量

开发中,我们想在类中定义一个静态常量,例如数学中常用的圆周率π, 通常使用public static final修饰的变量来完成定义。此时变量名用全部大写,多个单词使用下划线连接。

格式:

public static final 数据类型 变量名 = 值;

举例:

class MyMath{
public static final double PI = 3.1415926;
}

当我们想使用类的静态成员时,不需要创建对象,直接使用类名来访问即可。

System.out.println(MyMath.PI);

注意: 接口中的每个成员变量都默认使用public static final修饰

所有接口中的成员变量已是静态常量,由于接口没有构造方法,所以必须显示赋值。可以直接用接口名访问。

interface Inter {
	public static final int COUNT = 100;
}

Inter.COUNT

1.7 静态导入

静态导入就是java包的静态导入,使用import static 静态导入包 , 这样可以直接使用方法名去调用静态的方法

格式:

import static 包名.类名.方法名;
import static 包名.类名.*;

举例:
定义A类 如下, 含有两个静态方法 :

package net.csdn; 
public class A {
    public static void print(Object s){
        System.out.println(s);
    }

    public static void print2(Object s){
        System.out.println(s);
    }
}

静态导入一个类的某个静态方法 , 使用static和类名A .方法名 , 表示导入A类中的指定方法

import static net.csdn.A.print; //导包
public class Demo {
    public static void main(String[] args) {
        print("test string");
    }
}

如果有多个静态方法 , 使用static和类名A . * , 表示导入A类里的所有的静态方法

import static net.csdn.A.*;
public class Demo {
    public static void main(String[] args) {
        print("test string");
        print2("test2 string");
    }
}


二、内部类

2.1 概述

将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类


2.2 成员内部类

成员内部类 :定义在类中方法外的类。

格式:

class 外部类 {
    class 内部类{

    }
}

在描述事物时,若一个事物内部还包含其他事物,就可以使用内部类这种结构。比如,汽车类Car 中包含发动机类Engine ,这时,Engine就可以使用内部类来描述,定义在成员位置。

例如:

class Car { //外部类
    class Engine { //内部类

    }
}

访问特点

  • 内部类可以直接访问外部类的成员,包括私有成员。

  • 外部类要访问内部类的成员,必须要建立内部类的对象。

创建内部类对象格式:

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

举例:

public class Person {
    private  boolean live = true;
    class Heart {
        public void jump() {
            // 直接访问外部类成员
            if (live) {
                System.out.println("心脏在跳动");
            } else {
                System.out.println("心脏不跳了");
            }
        }
    }

    public boolean isLive() {
        return live;
    }

    public void setLive(boolean live) {
        this.live = live;
    }

}

测试类:

public class InnerDemo {
    public static void main(String[] args) {
        // 创建外部类对象 
        Person p  = new Person();
        // 创建内部类对象
        Person.Heart heart = p.new Heart();
        // 调用内部类方法
        heart.jump();
        // 调用外部类方法
        p.setLive(false);
        // 调用内部类方法
        heart.jump();
    }
}

结果:
心脏在跳动
心脏不跳了

内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号 。
比如,Person$Heart.class


2.3 匿名内部类

匿名内部类 :是内部类的简化写法。它的本质是一个带具体实现的 父类或者父接口的 匿名的 子类对象


开发中,最常用到的内部类就是匿名内部类了。以接口举例,当你使用一个接口时,似乎得做如下几步操作,

  1. 定义子类
  2. 重写接口中的方法
  3. 创建子类对象
  4. 调用重写后的方法

我们的目的,最终只是为了调用方法,那么能不能简化一下,把以上四步合成一步呢?匿名内部类就是做这样的快捷方式。


前提:

存在一个类或者接口,这里的类可以是具体类也可以是抽象类


格式:

new 父类名或者接口名(){
	// 并不是父类或者接口可以new了, new后的{}内的内容就是对其的实现
    // 方法重写
    @Override 
    public void method() {
        // 执行语句
    }
};


使用方式:

以接口为例,匿名内部类的使用

public abstract class FlyAble{
    public abstract void fly();
}

匿名内部类可以通过多态的形式接收

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

        // 1.等号右边:定义并创建该接口的子类对象
        // 2.等号左边:是多态,接口类型引用指向子类对象
        FlyAble  f = new FlyAble(){
       		@Override 
			public void fly() {
				System.out.println("芜湖起飞");
			}
		};
	}
}

匿名内部类直接调用方法

public class InnerDemo02 {
    public static void main(String[] args) {
       	new FlyAble(){
            public void fly() {
                System.out.println("芜湖起飞");
            }
        }.fly(); // 实现类调用重写方法
    }
}

方法的形式参数是接口或者抽象类时,也可以将匿名内部类作为参数传递

public class InnerDemo3 {
    public static void main(String[] args) {     	  
       	// 创建匿名内部类,直接传递给showFly(FlyAble f)
        showFly( new FlyAble(){
            public void fly() {
                System.out.println("芜湖起飞");
            }
        });
    }

    public static void showFly(FlyAble f) {
        f.fly();
    }
}


三、引用类型的传递

3.1 类名作为方法参数和返回值

  • 类名作为方法的形参

    方法的形参是类名,其实需要的是该类的对象,实际传递的是该对象的地址值

  • 类名作为方法的返回值

    方法的返回值是类名,其实返回的是该类的对象, 实际传递的,也是该对象的地址值

举例:

public class Person{
	public void eat(){
		System.out.println("人吃饭");
	}
}
public class Test{
	public static void main(String[] args){
		method(new Person());
		Person p = method2();
	}
	pubic static void method(Person p){
		p.eat();
	}
	public static Person method2(){
    	return new Person();
	}
}


3.2 抽象类作为形参和返回值

  • 方法的形参是抽象类名,其实需要的是该抽象类的子类对象

  • 方法的返回值是抽象类名,其实返回的是该抽象类的子类对象

public abstract class Animal{
	public abstract void eat();
}
public class Cat extends Animal{
	public void eat(){
		System.out.println("猫吃鱼");
	}
}
public class Test{
	public static void main(String[] args){
		method(new Cat());
		Animal a = method2();
    }
	public static void method(Animal a){
		a.eat();
	}
	public static Animal method2(){
    	return new cat();
	}
}

3.3 接口名作为形参和返回值

  • 方法的形参是接口名,其实需要的是该接口的实现类对象

  • 方法的返回值是接口名,其实返回的是该接口的实现类对象

public interface Fly{
	public abstract void fly();
}
public class Bird implements Fly{
	public void fly(){
		System.out.println("芜湖起飞");
	}
}

public class Test{
	public static void main(String[] args){
		method(new Bird());
		Fly f = method2();
	}
	public static void method(Fly f){
    	f.fly();
	}
	public static Fly method2(){
    	return new Bird();
	}
}

四、综合练习

4.1 综合问题

abstract关键字是什么可以修饰哪些?

抽象修饰符,可以修饰类、方法

final关键字是什么可以修饰哪些?

最终修饰符,可以修饰类、方法、成员变量、局部变量

static关键字是什么可以修饰哪些?

静态修饰符,可修饰内部类、方法、成员变量

private能不能和abstract一起使用?

不能,子类必须重写父类或接口的方法,而private子类无法直接访问

final能不能和abstract一起使用?

不能,final修饰的类不能被继承,抽象的子类必须继承后才能使用
final修饰的方法不能被重写,抽象类的的方法子类必须全部重写

static能不能和abstract一起使用?

不可以,如果一起使用,就会出现可以类名.调用的抽象方法,这个方法没有方法体,没有意义

static能不能和final一起使用?

可以,静态常量就是


4.2 代码题

按照以下要求定义类

员工类  
	属性 
		id 
		name
		基本工资
		
	行为 
		工作       抽象
		计算工资   抽象

经理类 
	属性 
		id 
		name
		基本工资
		管理工资
	行为 
		工作 
		计算工资  基本工资+管理工资
程序员
	属性 
		id 
		name
		基本工资
		项目奖金
	行为 
		工作 
		计算工资  基本工资+项目奖金 
公司类 
	属性
		公司名称
	行为 
		
		查看员工工资(员工){
		     公司名称:xxx公司
			员工的工号:38250
			员工的姓名:柳岩
			员工的职位:经理
			员工的工资:11111.00
		}
测试类 
	创建公司对象 指定公司名称
	调用查看员工工资的方法  查看一个经理的工资  
	调用查看员工工资的方法  查看一个程序员的工资

参考:

//公司
public class Company {
    String mingCheng;
    public Company() {
    }

    public Company(String mingCheng) {
        this.mingcheng = mingCheng;
    }

    public void check(Employee e) {
        System.out.println("公司名称: " + mingcheng + "公司");
        System.out.println("员工的工号: " + e.getId());
        System.out.println("员工的姓名: " + e.getNam());
        if (e instanceof Manager) {
            Manager m = (Manager) e;
            System.out.println("员工的职位: 经理");
            System.out.println("员工的工资: " + m.calcuateSalary());
        }
        if (e instanceof Programmer) {
            Programmer p = (Programmer) e;
            System.out.println("员工的职位: 程序员");
            System.out.println("员工的工资: " + p.calcuateSalary());
        }
    }
}

//员工抽象类
public abstract class Employee {
    private String id;
    private String nam;
    private double salary;

    public Employee() {
    }

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

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getNam() {
        return nam;
    }

    public void setNam(String nam) {
        this.nam = nam;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

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

    public abstract void work();
    public abstract double calcuateSalary();

}

//经理
public class Manager extends Employee{
    private double guanLiFei;

    public Manager() {
    }

    public Manager(String id, String nam, double salary, double guanLiFei) {
        super(id, nam, salary);
        this.guanLiFei = guanLiFei;
    }

    public double getGuanLiFei() {
        return guanLiFei;
    }

    public void setGuanLiFei(double guanLiFei) {
        this.guanLiFei = guanLiFei;
    }

    @Override
    public void work() {
        System.out.println("经理工作");
    }

    @Override
    public double calcuateSalary() {
        double total = guanLiFei+getSalary();
        return total;
    }
}

//程序员
public class Programmer extends Employee {
    private double jiangJin;

    public Programmer() {
    }

    public Programmer(String id, String nam, double salary, double jiangJin) {
        super(id, nam, salary);
        this.jiangJin = jiangJin;
    }

    public double getJiangJin() {
        return jiangJin;
    }

    public void setJiangJin(double jiangJin) {
        this.jiangJin = jiangJin;
    }

    @Override
    public void work() {
        System.out.println("程序员工作");
    }

    @Override
    public double calcuateSalary() {
        double total = jiangJin+getSalary();
        return total;
    }
}

//测试类
public class Test {
    public static void main(String[] args) {
        Company cp = new Company("CSDN");
        Manager m = new Manager("001", "张三", 10000, 10000);
        Programmer p = new Programmer("002", "小四", 2000, 5000);

        cp.check(m);
        System.out.println("--------------");
        cp.check(p);
    }
}


总结


左上角主页里面有所有系列文章喔!

消除贫穷的最好办法就是和我一起学大数据,加油,奥利给!

看到这里点个赞吧!

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。在编写C程序时,需要注意变量的声明和定义、指针的使用、内存的分配与释放等问题。C语言中常用的数据结构包括: 1. 数组:一种存储同类型数据的结构,可以进行索引访问和修改。 2. 链表:一种存储不同类型数据的结构,每个节点包含数据和指向下一个节点的指针。 3. 栈:一种后进先出(LIFO)的数据结构,可以通过压入(push)和弹出(pop)操作进行数据的存储和取出。 4. 队列:一种先进先出(FIFO)的数据结构,可以通过入队(enqueue)和出队(dequeue)操作进行数据的存储和取出。 5. 树:一种存储具有父子关系的数据结构,可以通过中序遍历、前序遍历和后序遍历等方式进行数据的访问和修改。 6. 图:一种存储具有节点和边关系的数据结构,可以通过广度优先搜索、深度优先搜索等方式进行数据的访问和修改。 这些数据结构在C语言中都有相应的实现方式,可以应用于各种不同的场景。C语言中的各种数据结构都有其优缺点,下面列举一些常见的数据结构的优缺点: 数组: 优点:访问和修改元素的速度非常快,适用于需要频繁读取和修改数据的场合。 缺点:数组的长度是固定的,不适合存储大小不固定的动态数据,另外数组在内存中是连续分配的,当数组较大时可能会导致内存碎片化。 链表: 优点:可以方便地插入和删除元素,适用于需要频繁插入和删除数据的场合。 缺点:访问和修改元素的速度相对较慢,因为需要遍历链表找到指定的节点。 栈: 优点:后进先出(LIFO)的特性使得栈在处理递归和括号匹配等问题时非常方便。 缺点:栈的空间有限,当数据量较大时可能会导致栈溢出。 队列: 优点:先进先出(FIFO)的特性使得

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值