java的面向对象(从入门到深入)

news2024/11/13 6:34:32

目录

一、基本概念:

1.类

2.对象

3.继承

4.多态

5.封装

6.方法

7.接口

8.抽象

二、深入概念:

三:总结


一、基本概念:

1.类

类就是一个一个东西的蓝图,里面有着它的属性和方法。

2.对象

对象是一个类的实例化。

3.继承

继承就是拥有父类的属性和方法。

4.多态

多态就是在不同情况对象有着不同的形态,通过方法重写或重载。

5.封装

封装就是把类中的属性私有化,只能通过公共方法访问。我们的属性只能通过public的set和get方法访问,而不能直接修改。

6.方法

方法就是定义在类中的行为,比如我们的get和set方法还有work方法。

7.接口

接口定义了类中必须要实现的方法。

注意:如果我们的父类实现了接口,那么子类也可以直接使用父类的接口方法,而不需要用implements实现接口。

8.抽象

使用抽象类定义子类必须实现的方法。

注意以下几点:

(1)我们自己在写一些类的时候发现他们之间有共性,所以我们为了简化,可以将公共逻辑提取出来写写一个抽象类,这样可以减少代码冗余。

(2)抽象类只是在普通类的基础上增加了抽象方法,正因如此它不可以直接实例化,因为它的抽象方法没有方法体,所以不可方法调用,故无法实例化。

(3)抽象类必须要有子类继承,一个子类只能继承一个抽象类,并且子类必须重写抽象类的所有抽象方法,否则必须也要命名为抽象类。

(4)关于抽象类用final和static声明的问题:

final的类是不可变的,所以不可以被继承,那么自然抽象类不可以用final修饰。

外部抽象类不能直接用static修饰,而内部抽象类可以用static修饰,修饰后,别的类要继承它只需要用它的外部类.内部类即可。

二、深入概念:

1.类中变量:

一个类中存在这样一些变量,分别是局部变量,成员变量,类变量。

局部变量存在于构造方法,方法,或者语句块内,变量声明和初始化都在其中,在方法执行完后就销毁。

成员变量定义在类中,方法体之外,可以被构造方法,方法,语句块内访问。

类变量也是声明和定义在类中,方法体之外,但必须用static修饰。

2.构造方法:

如果一个类中没有构造方法,那么java虚拟机会默认提供一个无参的构造方法。

3.一个源文件只能有一个public类,可以有多个非public类。

4.三种变量的访问方法:

局部变量:直接使用。

子类成员变量:this.成员变量

父类成员变量:super.成员变量

5.内部类有4种类型:成员内部类,局部内部类,静态内部类,匿名内部类

如果内部类不想被外部类访问可以给内部类加private修饰

成员内部类:作为外部类的一个成员,可以访问外部类的所有成员,包括私有字段

方法:首先创建外部类的对象,然后通过外部类.内部类,就可以在外部类对象的基础上new出内部类对象。

局部内部类:指在方法中定义的类,只在方法中可见,可访问外部类成员以及方法内局部变量(需要声明为final)

方法:在外部类的方法中调用创建内部类对象,并调用方法

静态内部类:只能访问外部类的静态成员变量和静态成员方法。

方法:不需要创建外部类的对象就可以访问,即可以独立存在。

注意:外部类不能用static修饰。

匿名内部类:指没有类名的内部类,用于简化接口和继承

分为两种形式:第一种匿名类继承一个父类,第二种匿名类实现一个接口

下面是第一种形式:

下面是第二种形式:

6.java中的不可变类:

不可变类即在创建对象后不可改变其属性。

注意以下几点:

(1)声明的类用final修饰,防止子类继承。

(2)类中的字段都用final或private修饰。

(3)通过构造函数初始化所有字段,不提供修改字段的方法。

(4)java中常见的不可变类有String,Integer,BigDecimal,LocalDate……

不可变类优缺点:

优点:

(1)线程安全:由于不可修改,故天然就是线程安全的,无需在并发下同步。

(2)缓存友好:不可变对象可以安全的缓存和共享。

(3)防止状态不一致:避免对象被修改而导致不一致的问题。

(4)哈希值不会反复变化,提高哈希表等数据结构的性能。哈希值在第一次计算出来放进缓存中,这就提高了哈希表的性能,不会反复计算。

缺点:由于可能会频繁的创建对象,所以性能开销较大。

下面通过String类的源码讲解一下:

我们可以看到String类使用final修饰的,并且内部用的是byte[]数组存储的(JDK8中是char),那么为何不用char类型呢?其实是为了节省字符串所占有的内存空间。同时还有另一个好处,那就是减少GC(垃圾回收次数减少)

同时String类实现了Serializable接口,Comparable接口,前者意味着可以序列化,后者意味着可以用compareTo方法比较。注意:"=="是用来比较两个对象的地址的,我们可以用equals方法去比较字符串的内容。

更深入一点:

现在的JDK使用coder来表示编码,那先说说字符集吧:

ASCLL,Latin1,Unicode,UTF-8

(1)ASCLL码表实现的是阿拉伯数字和英文字母,以及一些其它的字符,对于英语国家是够用的,但无法表达别的国家的文字。ASCLL码表用一个字节储存,最高位为奇偶效验位,其余7位为存储位。其它大多数编码都是兼容ASCLL码表的。

(2)Latin1是一种单字符集,也就是说最多只能表示256个字母或符号。Latin1是Mysql默认的编码形式。

(3)Unicode是一个庞大的字符集,目前可容纳100多万个字符,几乎可以表达出地球上所有的文字。但是使用的存储空间会稍大一点。

(4)UTF-8是使用最广的一种Unicode编码的实现形式,可以随着不同的符号变换字节长度。注意如果文件中有UTF-8编码的文字,又有GB系列编码的文字,那么就会导致乱码,因为二者不兼容。

在jvm里char是占用两个字节的,使用UTF-8编码,那么也就是说如果我的String类型的字符只用一个字节就可以表示,它也要占用两个字节。

当我们使用byte类型存储,并且使用Latin1字符编码,就会比UTF-8节省很多空间。

下面再说说字符串常量池:

java中存在着字符串常量池,当我们有相同的字符串时,那么这两个字符串指向同一个对象。提高性能,降低内存开销。来想下面一行代码:

String s = new String("abc");

思考一下,它创建了几个对象。

答案是两个,为啥呢?往下看。

当我们使用new创建一个字符串对象时,jvm会先在字符串常量池找有没有这个值的对象,如果有,那么就不会在常量池中创建对象了,而是直接在堆中创建"abc"这个字符串对象。然后将它的地址返回给变量s。变量s在栈上。

如果字符串常量池没有这个对象,那么就会先在常量池中创建"abc"这个字符串对象,然后在堆上创建"abc"这个字符串对象,然后将这个地址返回给s。变量s在栈上。

在java中,对象本身都在堆中,而基本数据类型变量和对象的引用都在栈上。

但是一般我们不通过new来创建字符串对象。看下面的代码:

String s = "abc";

当我们执行上面一行代码时,jvm会先在字符串常量池中找有没有"abc"的对象,如果有,则不用创建任何对象,而是直接将字符串常量池的这个对象地址返回给s。即此时堆中无new出来的对象。只有栈中的s变量去调用字符串常量池的相应对象地址。

如果字符串常量池中没有这个对象,那么现在字符串常量池中创建"abc"这个对象。然后将这个地址返回给s。

所以,如果使用new关键字,那么堆中就有两个对象,如果不使用new关键字,那么堆中只有一个对象,即字符串常量池的那个。

再深入一下intern()方法。

我们之前说过"=="比较的是地址是否相等,equals比较的是内容是否相等。

我们看到下面的代码,s变量指向的是堆中new出来的字符串对象,而ss变量指向的是在字符串常量池中的字符串对象。所以地址不一样,返回false。

 

然而思考一下下面的代码:

为什么现在返回的是true呢?下面将给出解释:

首先在字符串常量池中先创建"def"和"ghi",然后在堆中创建两个匿名对象(也叫临时对象,生命周期一般较短),然后在堆上创建一个新的对象"defghi"(此时字符串常量池没有这个对象),然后b引用这个对象。继续,在字符串常量池找"defghi"这个对象是否存在,此时不存在,但是堆中已经有了这个对象了。那么现在字符串常量池就保存堆中"defghi"这个对象的引用。即现在b和bb的引用地址一直,故返回true。

再说说"+"是怎么拼接两个字符串的吧,实际上,实现创建了一个StringBuilder的对象,然后用append()把"def"和"ghi"加进去,最后使用toString()方法返回新的字符串对象。

我们知道StringBuilder是可变长的字符串变量,不是常量,那么自然不会在字符串常量池中创建。

最后在讲一讲String,StringBuffer,StringBuilder的区别:

String是不可变的,适用于字符串不会频繁变化的场景。

StringBuffer是可变的,内部使用了synchronized关键字保证了线程安全。适用于多线程下频繁改变字符串的场景。

StringBuilder是可变的,不保证线程安全,性能比StringBuffer更好(去掉了保证线程安全的部分)。减少了开销。

那么我们String类到此为止,希望能够对您有所帮助。

7.方法重载与方法重写:

方法重载为一个方法有着不同的参数。

方法重写为子类在继承父类时,可以重写父类中的一些方法,从而实现多态性。

注意:重载与返回值没有关系。重写时,子类的方法访问级别不能比父类更严格。即父类为protected,子类不能为private。子类抛出的异常必须与父类一致,或者是父类异常的子类。

8.为什么要经常重写hashCode和equals方法:

两个方法的关系:如果equals相同,那么hashcode值必须相同,反过来则不一定相同。

在使用HashMap和HashSet等集合时,这些集合利用equals和hashCode确定元素的存储位置。如果不正确重写这两个方法,会导致无法判断对象的相等性。

重写equals方法,必须重写hashCode方法,因为两个对象如果equals方法相等,那么必须hashCode也是返回相等的值。

在基于哈希的数据结构,如果要判断是相等的,那么必须要先用hashCode方法判断哈希码是否相等,再用equals方法判断是否真正相等。由于不同的对象可能有着相同的哈希码,所以会用equals方法判断是否真正相等。

9.静态方法与实例方法:

特性静态方法实例方法
关键字static
归属对象
调用方式通过类名或对象对象
访问权限静态变量,静态方法静态变量,静态方法,实例变量,实例方法
用途工厂类方法,工厂方法改变对象的状态
生命期类加载时存在,类卸载时消失对象创建时存在,对象销毁时消失

10.Object类:

getClass方法:返回对象运行时的信息,通过该方法了解对象的实际类型。

常用于反射机制。

hashCode方法:返回对象的哈希码,哈希码用于在基于哈希的数据结构中,快速地查找对象。当重写equals方法时,也要重写hashCode方法,确保相等的对象有着相同的哈希码。

equals方法:比较两个对象的地址值是否相等,如要比较内容是否相等,需重写equals方法。

clone方法:创建并返回该对象的副本,默认是浅拷贝。即复制对象本身,但不复制其内部引用。

为了使用该方法,类需要实现Cloneable接口,并重写clone方法,否则会抛出异常。

toString方法:返回对象的字符串表现形式,默认返回对象的类名和内存地址的组合。

常常重写该方法返回有意义的字符串。

notify方法:唤醒一个等待在该对象上的线程。

该方法通常与synchronized和wait()方法一起使用,起到线程之间的协调。

notifyAll方法:唤醒所有等待在该对象上的线程。

wait方法有三个:

第一个:无限期等待。

第二个:等待指定的毫秒数。

第三个:等待指定的毫秒数和指定的纳秒数。

通常与synchronized一起使用,达到线程间的协调。

finalize方法:垃圾回收器回收对象时使用,用于清理工作。但不推荐使用,因为java的垃圾回收机制不可预测且过时,所以常使用try-with-resources和AutoCloseable接口进行资源管理。

11.包:

(1)将功能相似的类或者接口放在一个包下,便于类的查找与使用。

(2)包可以避免命名冲突。同一个包中的类名可以是不同的,但是不同的包的类名可以是相同的,只需要用包名加以区分即可。

(3)包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

既然说到了打包,那再来说说导包吧:

import关键字:为了使用别的包中成员,我们需要在程序中导入该包。

12.基本类型和包装类型:

基本类型:java中有8个基本类型,是直接存储数值的,变量位置取决于作用域和声明方式。

分别为short, int,  long, float, double, boolean, char, byte.

包装类型:java中每个基本类型都有一个包装类型,包装类型是类,存储在堆上,可用于面向对象编程。

分别为Short, Integer, Long, Float, Double, Boolean, Character, Char, Byte.

区别:

(1)性能方面:

基本类型占用内存小,效率高。

而包装类型由于是对象,需要涉及内存分配和垃圾回收,性能较低。

(2)比较方式不同:

基本类型只需==就可以判断是否相等。

而包装类型的==是判断对象地址是否相等,使用equals是判断对象内容是否相等。

(3)默认值不同:

基本类型默认值为0或false.

而包装类型的默认值为null.

(4)初始化方式不同:

基本数据类型直接赋值即可。

而包装类型需要new一个对象。

(5)存储方式不同:

基本类型如果是局部变量那么就存储在栈上面,如果是成员变量就存储在堆上面。

而包装类型保存在堆上。

自动装箱与拆箱:

在java中,我们很多时候用到的是包装类型而不是基本类型。在集合当中,我们是不能讲int,double这些类型放进去的,因为集合的中的元素要求是Object类型的,那么为了让基本类型有对象的性质,就把它们包装起来,并添加了相应的属性和方法。

装箱:基本类型自动转为包装类型对象。

拆箱:包装类型对象自动转为基本类型。

缓存机制:

包装类型中的Byte,Short,Interger, Long对一些范围内的值提供了缓存,提升了性能。

下面会通过Integer缓存池详细讲解:

java中的Integer缓存池是为了节省内存,提升性能的,因为实践中大多数操作都集中在值很小的范围内,因此缓存下来可以节省内存分配和垃圾回收的负担,提高性能。

java中Integer缓存的值在-128到127,这些值会被缓存下来复用。

过程:java在自动装箱时,如果int的范围在-128到127之间,会直接返回一个已经缓存的Integer对象,而不是创建新的对象。因此,同一数值的包装类型对象可能是同一实例。

下面是值在缓存池范围内的情况

下面是值不在缓存池范围内的情况

额外扩展:

Long, Short,Byte缓存范围也是-128到127

Float和Double没有缓存池,因为小数可以存的很多。

Character缓存范围为0到127,即ASCLL码表。

Boolean缓存两个值,true和false。

下面给出长度的总结: 

byte(Byte):1字节 -128到127

short(Short):2字节 -32768到32767

int(Integer):4字节 -21474836482147483647

long(Long): 8字节 -92233720368547758089223372036854775807

char(Character):2字节 Unicode字符集中任意字符

float(Float):4字节 约为-3.4E38到3.4E38

double(Double):8字节 约为-1.7E108到1.7E308

13.static关键字:

static的作用有许多:

首先来看下面代码

当我们如果要创建很多个学生对象时,那么每个对象的三个属性都会占用一定的内存,但是其实这些学生的school属性都是相同的,我们如果创建10000个学生对象,那么这10000个学生对象都各自占用一部分内存给school,那么是不是太浪费了?所以我们可以用static修饰,这样我们只要占用1块内存,而不是10000块。

那么此时我们的变量a在栈上,指向的是在堆中的对象的地址,其对象中有张三和18两个属性。

变量b也在栈上,指向的是在堆中对象的地址,其对象中有李四和16两个属性。

我们还有一个静态区,里面存放着school属性"MIT"。

再看下面一段代码:

我们每次创建对象,对象中都有各自的age值,自增完在打印,所以结果都为1,那么我们如果加上static修饰呢?

由于现在的age在静态区,所以我们每次都会自增静态区中的age,所以我们打印的为1,2,3。

这就是静态变量和成员变量之间的区别。

下面再说说静态方法吧:

(1)静态方法属于这个类,但是不是这个类的对象。

(2)调用静态方法时不用创建这个类的对象。

(3)静态方法可以访问静态变量。

change是一个静态方法,所以可以直接访问到静态变量age并修改,并且调用的时候直接用类名.上静态方法即可。主要,静态方法不可调用非静态方法和非静态变量。

那么我们可能会思考为什么main方法是用static修饰的呢?

public static void main(String[] args)

首先我们已经知道静态方法是不用创建对象的,所以,如果不是静态的,对于jvm而言,在执行时要先创建对象,但是main函数是程序执行的入口,创建一个对象就显得多余了,所以用static修饰。

下面再说说静态代码块吧:

来看下面的代码:

我们看到静态代码块优先于main函数执行。但是程序中没有main方法在JDK1.6是可以的,但是在JDK7就不行了。

那么实际开发中静态代码块到底有什么用呢?

a是一个静态的ArrayList,所以不太可能在初始声明时就初始化,因此我们可以在静态代码块中完成初始化。在开发中,我们常常使用静态代码块配置文件到内存中。

14.instanceof关键字

instanceof关键字是判断对象是否是指定的类型。如果不判断的话那么可能会出现ClassCastException 异常。

来看instanceof的运用

最后的结果是true,因为Bigtree是tree的子类,所以说Bigtree和Tree是is-a的关系,故返回true.

同理,对于接口也是如此。

再看以下代码,是我们比较常用的方式,先把当前对象使用instance进行类型判断,然后进行类型强制转换。以下就是两种方式:

第二种方式是JDK16的时候新增的,使代码更加便捷。

三:总结

看到这里,您是不是对于java的面向对象已经有所了解了呢?本文中的所有代码难度不大,应该对初学者比较友好,可以自己练习一下,毕竟编程最重要的就是实践,没有亲自去写,那么就不能抓住代码中的细枝末节,当然也就没有彻底理解。所以,大家要多写,多练,这样才能提高自己!

如果有疑问或者错误的地方可以私信我或者评论区留言。

感谢您的阅读,我们下篇文章详解JAVA集合时再回。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2236817.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FPGA实现串口升级及MultiBoot(六)ICAPE2原语实例讲解

本文目录索引 一个指令和三种方式通过ICAPE2原语添加ICAPE2 IP构建Golden位流工程MultiBoot位流工程验证example2总结代码缩略词索引: K7:Kintex 7V7:Vertex 7A7:Artix 7MB:MicroBlaze上一篇文章种总结了MultiBoot 关键技术,分为:一个指令、二种位流、三种方式、四样错误。针…

自动泊车端到端算法 ParkingE2E 介绍

01 算法介绍 自主泊车是智能驾驶领域中的一项关键任务。传统的泊车算法通常使用基于规则的方案来实现。因为算法设计复杂,这些方法在复杂泊车场景中的有效性较低。 相比之下,基于神经网络的方法往往比基于规则的方法更加直观和多功能。通过收集大量专家…

sealos部署K8s,安装docker时master节点突然NotReady

1、集群正常运行中,在集群master-1上安装了dockerharbor,却发现master-1节点NotReady,使用的网络插件为 Cilium #安装docker和harbor(docker运行正常) rootmaster-1:/etc/apt# apt install docker-ce5:19.03.15~3-0~u…

什么是磁场探针台

探针台主要应用于半导体行业、光电行业、集成电路以及封装的测试。广泛应用于复杂、高速器件的精密电气测量的研发,旨在确保质量及可靠性,并缩减研发时间和器件制造工艺的成本。 磁场探针台就是在普通探针台的基础上,增加了磁性测量环境&…

【八百客CRM-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…

iOS SmartCodable 替换 HandyJSON 适配记录

前言 HandyJSON群里说建议不要再使用HandyJSON,我最终选择了SmartCodable 来替换,原因如下: 首先按照 SmartCodable 官方教程替换 大概要替换的内容如图: 详细的替换教程请前往:使用SmartCodable 平替 HandyJSON …

✍Qt自定义带图标按钮

✍Qt自定义带图标按钮 📝问题引入 近段时间的工作中,有遇到这样一个需求 📝: 一个按钮,有normal、hover、pressed三种状态的样式,并且normal和hover样式下,字体颜色和按钮图标不一样。 分析…

OpenGL学习笔记(三) 绘制图形

glFrontFace(GL_CCW); // 设置CCW方向为“正面”&#xff0c;CCW即CounterClockWise&#xff0c;逆时针 glFrontFace(GL_CW); // 设置CW方向为“正面”&#xff0c;CW即ClockWise&#xff0c;顺时针#include <GL/glut.h>#include <math.h> void myDisplay(voi…

通过代码复习回忆 DiffusionDet: DiffusionTracker

DiffusionDet : DiffusionTracker复习回顾 之前的一段时间学习了基于扩散模型的检测于跟踪算法&#xff0c;最近在忙别的事情就导致了这里存在了很多和细节上的遗忘在这里进行一定的回顾&#xff0c;之后在试图看看可以进一步学习基于点集的扩散过程吗&#xff1f; Diffusion…

单体架构的 IM 系统设计

先直接抛出业务背景&#xff01; 有一款游戏&#xff0c;日活跃量&#xff08;DAU&#xff09;在两千左右&#xff0c;虽然 DAU 不高&#xff0c;但这两千用户的忠诚度非常高&#xff0c;而且会持续为游戏充值&#xff1b;为了进一步提高用户体验&#xff0c;继续增强用户的忠…

Java-字符串常量池

在Java程序中&#xff0c;类似于&#xff1a;1&#xff0c; 2&#xff0c; 3&#xff0c;3.14&#xff0c;“hello”等字面类型的常量经常频繁使用&#xff0c;为了使程序的运行速度更快、 更节省内存&#xff0c;Java为8种基本数据类型和String类都提供了常量池。 1.为什么要…

Wot Design Uni高颜值、轻量化的uni-app组件库 快速入门

一、简介 Wot Design Uni是一个基于Vue3和TypeScript开发的高颜值、轻量化的uni-app组件库。它提供了超过70个高质量组件&#xff0c;这些组件覆盖了移动端的主流场景&#xff0c;使得开发者能够更加高效地进行移动应用的开发。 以下是Wot Design Uni的一些主要特点&#xff…

maven依赖无法导入爆红问题

1、属于公司内部依赖&#xff0c;当前项目没有连接到公司Maven私服 2、之前本地已经下载过&#xff0c;但是下载中途失败了&#xff0c;产生了一个xxx.jar.lastUpdated文件&#xff0c;此时Maven不会对该依赖再下载 引入本地仓库依赖

MyBatis xml 文件中 SQL 语句的小于号未转义导致报错

问题现象 在 MyBatis 的 xml 文件中添加了一个 SQL 语句 <select id"countXxx" resultType"int">select count(*) from t1 where count < 3 </select>启动 Spring Boot 应用程序后报错&#xff1a; Caused by: org.apache.ibatis.builde…

前端学习之ES6+

1.ES6是什么 ES6&#xff0c;全称是ECMAScript 6&#xff0c;是JavaScript语言的下一代标准&#xff0c;由ECMA国际组织在2015年6月正式发布。ES6也被称作ECMAScript 2015&#xff0c;从这个版本开始&#xff0c;ECMA组织决定每年发布一个新的ECMAScript版本&#xff0c;以使J…

学习笔记:黑马程序员JavaWeb开发教程(2024.11.8)

5.10 分层解耦-分层解耦&#xff08;IOC-DI&#xff09; 在之前写的代码中&#xff0c;Controller层中new了一个Service层中的对象&#xff0c;在Service层中类名改变&#xff0c;则Controller层中也需要变化&#xff0c;这就是两个层之中耦合较重&#xff0c;需要减少耦…

Python常见并行化方法及性能对比

Python代码中通常有三种实现并行化的方法 multiprocessing的同步方法&#xff0c;mapmultiprocessing的异步方法&#xff0c;apply_asyncRay提供的并行或分布式能力 Ray 和 Python 的 multiprocessing 模块都是用于并行和分布式计算的工具&#xff0c;但它们在设计目标、功能…

【软考】系统分析师第二版 新增章节 第20章微服务系统分析与设计

微服务系统是一类基于微服务架构风格的分布式系统&#xff0c;它将应用程序拆分成多个独立的小型服务&#xff0c;每个服务都运行在独立的进程中&#xff0c;并采用轻量级通信协议进行通信。这些服务可以由不同的团队开发、不同的编程语言编写&#xff0c;并且可以按需部署。微…

【WRF理论第七期】WPS预处理

【WRF理论第七期】WPS预处理 运行WPS&#xff08;Running the WPS&#xff09;步骤1&#xff1a;Define model domains with geogrid步骤2&#xff1a;Extracting meteorological fields from GRIB files with ungrib步骤3&#xff1a;Horizontally interpolating meteorologic…

【设计模式】行为型模式(一):模板方法模式、观察者模式

行为型模式&#xff08;一&#xff09;&#xff1a;模板方法模式、观察者模式 1.模板方法模式&#xff08;Template&#xff09;1.1 主要特点1.2 适用场景1.3 示例1.3.1 抽象类定义模板方法1.3.2 子类实现具体步骤1.3.3 客户端1.3.4 结果输出 2.观察者模式&#xff08;Observer…