static final 和final的区别
学习java的时候常常会被修饰符搞糊涂,这里总结下static final和final的区别。
static是静态修饰关键字,可以修饰变量和程序块以及类方法:
当定义一个static的变量的时候jvm会将将其分配在内存堆上,所有程序对它的引用都会指向这一个地址而不会重新分配内存;
当修饰一个程序块的时候(也就是直接将代码写在static{...}中)时候,虚拟机就会优先加载静态块中代码,这主要用于系统初始化;
当修饰一个类方法时候你就可以直接通过类来调用而不需要新建对象。
final可以修饰变量、方法及类:
当定义一个final变量时,jvm会将其分配到常量池中,程序不可改变其值;
当修饰一个方法时,该方法在子类中将不能被重写;
当修饰一个类时,该类不能被继承。
static变量
按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量,叫静态变量或类变量;另一种是没有被static修饰的变量,叫实例变量。
两者的区别是:
对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。
对于实例变量,没创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响(灵活)。
static方法
静态方法可以直接通过类名调用,任何的实例也都可以调用,因此静态方法中不能用this和super关键字,不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。
因为static方法独立于任何实例,因此static方法必须被实现,而不能是抽象的abstract。
1、static 强调只有一份,final 说明是一个常量,final定义的基本类型的值是不可改变的,但是fianl定义的引用对象的值是可以改变的,下面举个例子来说明:
package DifStaticFinalAndFinal;
class SelfCounter {
private static int counter;
private int id=counter++;
public String toString(){
return "SelfCounter: "+id;
}
}
package DifStaticFinalAndFinal;
class WithFinalFields {
static final SelfCounter wffs=new SelfCounter();
final SelfCounter wff=new SelfCounter();
public String toString(){
return "wff= "+wff+",\n wffs= "+wffs;
}
}
主函数:
package DifStaticFinalAndFinal;
public class StaticFinal {
public static void main(String[] args) {
System.out.println("First Object:");
System.out.println(new WithFinalFields());
System.out.println("Second Object:");
System.out.println(new WithFinalFields());
}
}
运行结果:
First Object:
wff= SelfCounter: 1,
wffs= SelfCounter: 0
Second Object:
wff= SelfCounter: 2,
wffs= SelfCounter: 0
分析为什么wff两次的运行结果不同,而wffs两次的运行结果相同?
因为wffs这个容器是用static final来定义的,static 强调只有一份,因此只有一个值,而final修饰的引用是可以变化的,因此wff的值是可以变化的,这也是final修饰基本类型和引用的不同。
2、在方法中将参数指明为final时,在使用该方法时,可以读参数但是无法使用该参数。
package cn.qdu.chapter7_example;
public class FinalArguments {
void with(final Gizmo g){
}
void without(Gizmo g){
g=new Gizmo();
g.spin();
}
int g(final int i){return i+1;}
public static void main(String[] args) {
FinalArguments bf=new FinalArguments();
bf.with(null);//不管这里的参数换成什么,都是执行void(final Gizmo g)方法,无法更改参数
bf.without(null);
}
}
3、为什么使用final方法呢?
原因有两个。
其一是把方法锁定,确保在继承中使用方法行为不变,并且不会被覆盖;
其二是效率,如果一个方法指明为final,就是同意编译器将针对该方法的所有调用都转为内嵌调用。 转为内嵌调用的目的是节省开销,因为编译器发现一个final方法调用命令时,会跳过程序代码这种正常方式而执行方法调用机制(将参数压入栈,跳至方法代码处并执行,然后跳回并清理栈中的参数,处理返回值),并且以方法体中的实际代码的副本来替代方法调用。但是如果一个方法很大,程序很膨胀,就会看不到内嵌带来的任何性能的提高。
4、final和private关键字
类中所有private方法都隐式地指定为是final的,因为private关键字只能被本类调用,其他类中的方法也无法覆盖private修饰的方法,因此和加上final效果是一样的。
5、当某个类的整体定义为final时,表明该类不能被继承,方法不能被覆盖,且final类中的所有方法都隐式指定为是final的,方法声明为final后还可以有效地“关闭”动态绑定。
6、static加载类的动作只发生一次。
最后,说了这么多,也要对final做一个客观的评价。若方法或类不想让别人来继承和修改,设定为final是明智的,但是在团体中这样会阻碍其他程序员通过你想不到的合理的途径来复用类,这样的话final方法就显得过于严苛了。
static final 和final的区别的更多相关文章
- -1-2 java 面向对象基本概念 封装继承多态 变量 this super static 静态变量 匿名对象 值传递 初始化过程 代码块 final关键字 抽象类 接口 区别 多态 包 访问权限 内部类 匿名内部类 == 与 equal
java是纯粹的面向对象的语言 也就是万事万物皆是对象 程序是对象的集合,他们通过发送消息来相互通信 每个对象都有自己的由其他的对象所构建的存储,也就是对象可以包含对象 每个对象都有它的类型 也就是 ...
- Java中 static、final和static final的特点及区别
final: final可以修饰:属性,方法,类,局部变量(方法中的变量) final修饰的属性的初始化可以在编译期,也可以在运行时,初始化后不能被改变. final修饰的属性跟具体对象有关,在运行期 ...
- java的static final和final的区别
转自:https://www.cnblogs.com/EasonJim/p/7841990.html 说明:不一定准确,但是最快理解. final: final可以修饰:属性,方法,类,局部变量(方法 ...
- Java中static final 与 final 的区别(转载)
转自:http://advance0683.iteye.com/blog/1107732 Java中static final 与 final 的区别: 例子: Java代码 import java.u ...
- 转(static final 和final的区别)
学习java的时候常常会被修饰符搞糊涂,这里总结下static final和final的区别. 1.static 强调只有一份,final 说明是一个常量,final定义的基本类型的值是不可改变的,但 ...
- Java中static、final和static final(final static)的区别(转)
大佬的总结(大赞!) final可以修饰:属性,方法,类,局部变量(方法中的变量) final修饰的属性的初始化可以在编译期,也可以在运行期,初始化后不能被改变. final修饰的属性跟具体对象有关, ...
- 【Java面试题系列】:Java中final finally finalize的区别
本篇为[Java面试题系列]第三篇,文中如有错误,欢迎指正. 第一篇链接:[Java面试题系列]:Java基础知识常见面试题汇总 第一篇 第二篇链接:[Java面试题系列]:Java基础知识常见面试题 ...
- 详解详解Java中static关键字和final关键字的功能
摘要:static关键字和final关键字是Java语言的核心,深入理解他们的功能非常重要. 本文分享自华为云社区<Java: static关键字与final关键字>,原文作者:唐里 . ...
- Android源码中final关键字的用法及final,finally,finalize的区别
Android开发的学习流程 final,finally,finalize的区别 Android的发展越来越快,Android开发人员越来越多,当两种情况碰撞,在诸多开发者中跟紧Android步伐脱颖 ...
随机推荐
- VS2019调试 asp.net core 2.2 出现《ANCM In-Process Handler Load Failure 发布后启动错误处理》处理
从 google 出来的 github 上 AspNetCore issues 和 stackoverflow 搜到的,百度 博客园搜到的,CSDN 搜到的,统统设置了,不管用. 从这些问题 ...
- Hive常见错误
1.root is not allowed to impersonate root 修改etc/hadoop/core-site.xml,增加如下配置: <property> <na ...
- gcd 题解
gcd Little White learned the greatest common divisor, so she plan to solve a problem: given \(x, n,\ ...
- Laravel文档工具
laravel-doc ⛵laravel-doc 是一个用来生成文档,通过markdown来撰写文档,并提供web访问文档的项目 安装要求 PHP >= 7.0.0 Laravel >= ...
- IP地址结构(转载)
分类寻址(网络号+主机号) 在最初定义Internet地址结构时,每个单播IP地址都有一个网络部分,用于识别接口使用的IP地址在哪个网络中可被发现:以及一个主机地址,用于识别由网络部分给出的网络中的特 ...
- IDEA中Tomcat部署时war和war exploded区别
原理说明 war模式:将WEB工程以包的形式上传到服务器 :war exploded模式:将WEB工程以当前文件夹的位置关系上传到服务器: 含义解释 war模式这种可以称之为是发布模式,看名字也知道, ...
- FMC与FPGA双口ram通讯
硬件环境:ARM+FPGA通过FMC互联,STM32F767和 EP4CE15F23I7 FMC设置,STM的系统时钟HCLK为216MHz /* FMC initialization functio ...
- MIME类型对应表:
MIME类型对应表: 常用MIME类型: 扩展名 MIME类型 .iso ISO File .rar application/x-rar-compressed .zip application/zip ...
- docker封装mysql镜像
一.概述 直接使用官方的镜像 docker pull mysql:5.7 但是mysqld.cnf并没有优化,还是默认的. 二.封装镜像 创建目录 # dockerfile目录 mkdir -p /o ...
- 『Tree nesting 树形状压dp 最小表示法』
Tree nesting (CF762F) Description 有两个树 S.T,问 S 中有多少个互不相同的连通子图与 T 同构.由于答案 可能会很大,请输出答案模 1000000007 后的值 ...