final与 static的区别;static代码块以及嵌套类介绍
本篇文章主要分为两个模块进行介绍:1.final,staic,static final之间的异同;2. static 模块;3.嵌套类的概念
1.final,staic,static final之间的异同:
(1)final
final可以修饰属性,方法,类,局部变量(静态变量、实例变量和局部变量);
其中,final修饰的属性表明是个常量,它的初始化可以在编译期,也可以在运行期,初始化后不能被改变;
final修饰的属性跟具体对象有关,在运行期初始化的final属性,不同对象可以有不同的值;
final修饰的方法不能被子类方法覆盖,但可以被继承;
private不能被子类方法覆盖,private类型的方法默认是final类型的
final修饰的类不能被继承,没有子类,final类中的方法默认是final的
final不能用于修饰构造方法;
另外,对于基本类型数据,final会将值变为一个常数(创建后不能被修改);但是对于对象句柄(亦可称作引用或者指针),final会将句柄变为一个常数(进行声明时,必须将句柄初始化到一个具体的对象。而且不能再将句柄指向另一个对象。但是,对象的本身是可以修改的。这一限制也适用于数组,数组也属于对象,数组本身也是可以修改的。方法参数中的final句柄,意味着在该方法内部,我们不能改变参数句柄指向的实际东西,也就是说在方法内部不能给形参句柄再另外赋值)。
(2)static
static修饰的属性、方法、代码段跟该类的具体对象无关,不创建对象也能调用static修饰的属性、方法等,
static和“this、super”势不两立,因为this、super正好跟具体对象有关。
也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。
(3)static final(等价于final staic,但是一般习惯staic在前)
static修饰的属性强调它们只有一个,final修饰的属性表明是一个常数(创建后不能被修改)。static final修饰的属性表示一旦给值,就不可修改,并且可以通过类名访问。static final也可以修饰方法,表示该方法不能重写,可以在不new对象的情况下调用
2.static{}代码块与普通{}代码块的区别
在类中,可以将某一块代码声明为静态的,这样的程序块叫静态初始化段。静态代码块的一般形式如下:
- //静态代码块
- static {
- 语句序列
- }
- //普通代码
- {
- 语句序列
- }
其中,静态代码块只能定义在类里面,它独立于任何方法,不能定义在方法里面。
静态代码块里面的变量都是局部变量,只在本块内有效。
静态代码块会在类被加载时自动执行,而无论加载者是JVM还是其他的类。
一个类中允许定义多个静态代码块,执行的顺序根据定义的顺序进行。
静态方法只能访问静态成员,实例方法可以访问静态和实例成员。之所以不允许静态方法访问实例成员变量,是因为实例成员变量是属于某个对象的,而静态方法在执行时,并不一定存在对象。同样,因为实例方法可以访问实例成员变量,如果允许静态方法调用实例方法,将间接地允许它使用实例成员变量,所以它也不能调用实例方法。基于同样的道理,静态方法中也不能使用关键字this。main()方法是一个典型的静态方法,它同样遵循一般静态方法的规则,所以它可以由系统在创建对象之前就调用。
例子1:
- public class staticBlock{
- //定义一个普通的main()方法
- public static void main(String args[]){
- System.out.println("This is main method.");
- }
- //定义一个静态代码块
- static{
- System.out.println("This is static block.");
- int stVar = 0; //这是一个局部变量,只在本块内有效
- }
- }
运行结果:
- This is static block.
- This is main method.
从以上输出结果中可以看出,静态代码块甚至在main方法之前就被执行。在main()方法中可以完成的任务在静态代码块中都可以完成。但是二者在执行上仍然有一些区别。
例子2:
- public class staticBlock{
- static int stMember = 100; //定义静态成员变量
- public static void main(String args[]){
- System.out.println("This is main method.");
- }
- //第一个静态代码块
- static{
- System.out.println("This is first static block.");
- stMember = 200; //访问静态成员变量
- staticBlock oa = new staticBlock(); //创建对象
- System.out.println("stMember = " + oa.stMember);
- statFun(); //调用静态方法
- }
- //定义一个静态方法
- static void statFun(){
- System.out.println("This is a static method.");
- }
- //第二个静态代码块
- static{
- System.out.println("This is second static block.");
- }
- }
运行结果如下:
- This is first static block.
- stMember = 200
- This is a static method.
- This is second static block.
- This is main method.
静态代码块与普通代码块的差异如下:
相同点:都是在JVM加载类时且在构造方法执行之前执行,在类中都可以定义多个,
一般在代码块中对一些static变量进行赋值。
不同点:静态代码块在非静态代码块之前执行(静态代码块—>非静态代码块—>构造方法)。
静态代码块只在第一次new执行一次,之后不再执行,而非静态代码块在每new
一次就执行一次。非静态代码块可在普通方法中定义(不过作用不大);而静态代码块不行。
例子:
- //普通类
- public class PuTong {
- public PuTong(){
- System.out.print("默认构造方法!-->");
- }
- //非静态代码块
- {
- System.out.print("非静态代码块!-->");
- }
- //静态代码块
- static{
- System.out.print("静态代码块!-->");
- }
- public static void test(){
- {
- System.out.println("普通方法中的代码块!");
- }
- }
- }
- //测试类
- publicclass TestClass {
- /**
- * 区别两次new静态与非静态代码块执行情况
- */
- public static void main(String[] args) {
- PuTong c1 = new PuTong();
- c1.test();
- PuTong c2 = new PuTong();
- c2.test();
- }
- }
/*
运行输出结果是:
静态代码块!-->非静态代码块!-->默认构造方法!-->普通方法中的代码块!
非静态代码块!-->默认构造方法!-->普通方法中的代码块!
*/
一般情况下,如果有些代码必须在项目启动的时候就执行的时候,需要使用静态代码块,这种代码是主动执行的;需要在项目启动的时候就初始化,在不创建对象的情况下,其他程序来调用的时候,需要使用静态方法,这种代码是被动执行的.
两者的区别就是:静态代码块是自动执行的;
静态方法是被调用的时候才执行的.
作用:静态代码块可用来初始化一些项目最常用的变量或对象;静态方法可用作不创建对象也可能需要执行的代码.
3.嵌套类概念
可以在一个类的内部定义另一个类,这种类称为嵌套类(nested classes),它有两种类型:静态嵌套类和非静态嵌套类。静态嵌套类使用很少,最重要的是非静态嵌套类,也即是被称作为内部类(inner)。嵌套类从JDK1.1开始引入。其中inner类又可分为三种:
其一、在一个类(外部类)中直接定义的内部类;
其二、在一个方法(外部类的方法)中定义的内部类;
其三、匿名内部类。
(1)静态嵌套类
- public class StaticTest {
- private static String name = "javaJohn";
- private String id = "X001";
- static class Person{
- private String address = "swjtu,chenDu,China";
- public String mail = "josserchai@yahoo.com";//内部类公有成员
- public void display(){
- //System.out.println(id);//不能直接访问外部类的非静态成员
- System.out.println(name);//只能直接访问外部类的静态成员
- System.out.println("Inner "+address);//访问本内部类成员。
- }
- }
- public void printInfo(){
- Person person = new Person();
- person.display();
- //System.out.println(mail);//不可访问
- //System.out.println(address);//不可访问
- System.out.println(person.address);//可以访问内部类的私有成员
- System.out.println(person.mail);//可以访问内部类的公有成员
- }
- public static void main(String[] args) {
- StaticTest staticTest = new StaticTest();
- staticTest.printInfo();
- }
- }
在静态嵌套类内部,不能访问外部类的非静态成员,这是由Java语法中"静态方法不能直接访问非静态成员"所限定。若想访问外部类的变量,必须通过其它方法解决,由于这个原因,静态嵌套类使用很少。注意,外部类访问内部类的的成员有些特别,不能直接访问,但可以通过内部类来访问,这是因为静态嵌套内的所有成员和方法默认为静态的了。同时注意,内部静态类Person只在类StaticTest 范围内可见,若在其它类中引用或初始化,均是错误的。
(2)外部内中的内部类
- public class Outer {
- int outer_x = 100;
- class Inner{
- public int y = 10;
- private int z = 9;
- int m = 5;
- public void display(){
- System.out.println("display outer_x:"+ outer_x);
- }
- private void display2(){
- System.out.println("display outer_x:"+ outer_x);
- }
- }
- void test(){
- Inner inner = new Inner();
- inner.display();
- inner.display2();
- //System.out.println("Inner y:" + y);//不能访问内部内变量
- System.out.println("Inner y:" + inner.y);//可以访问
- System.out.println("Inner z:" + inner.z);//可以访问
- System.out.println("Inner m:" + inner.m);//可以访问
- InnerTwo innerTwo = new InnerTwo();
- innerTwo.show();
- }
- class InnerTwo{
- Inner innerx = new Inner();
- public void show(){
- //System.out.println(y);//不可访问Innter的y成员
- //System.out.println(Inner.y);//不可直接访问Inner的任何成员和方法
- innerx.display();//可以访问
- innerx.display2();//可以访问
- System.out.println(innerx.y);//可以访问
- System.out.println(innerx.z);//可以访问
- System.out.println(innerx.m);//可以访问
- }
- }
- public static void main(String args[]){
- Outer outer = new Outer();
- outer.test();
- }
- }
以上代码需要说明有,对于内部类,通常在定义类的class关键字前不加public 或 private等限制符,若加了没有任何影响,同时好像这些限定符对内部类的变量和方法也没有影响(?)。另外,就是要注意,内部类Inner及InnterTwo只在类Outer的作用域内是可知的,如果类Outer外的任何代码尝试初始化类Inner或使用它,编译就不会通过。同时,内部类的变量成员只在内部内内部可见,若外部类或同层次的内部类需要访问,需采用示例程序中的方法,不可直接访问内部类的变量。
3.在代码块的作用域内定义内部类。
- public class Outer {
- private String outerName = "This is Outer Name";
- public void test() {
- for(int i=0;i<3;i++) {
- class Inner {
- public void display() {
- System.out.println(outerName);
- }
- }
- Inner inner = new Inner();
- inner.display();
- }
- }
- }
在上面的代码中,只能定义成class inner,不能定义成public class inner,因为此时是作为方法中的变量定义的,不是作为类的成员变量。
参考链接:
https://blog.csdn.net/qq_40665031/article/details/78440084
https://blog.csdn.net/hust_yfang/article/details/79585696
https://www.cnblogs.com/EasonJim/p/7841990.html
https://blog.csdn.net/leixiongbo/article/details/52161936
https://blog.csdn.net/WelcomeSpring/article/details/79430546
final与 static的区别;static代码块以及嵌套类介绍的更多相关文章
- 13_java之final|static|包|匿名对象|代码块|内部类
01final关键字概念 * A: 概述 继承的出现提高了代码的复用性,并方便开发.但随之也有问题,有些类在描述完之后,不想被继承, 或者有些类中的部分方法功能是固定的,不想让子类重写.可是当子类继承 ...
- Java基础进阶:继承重点摘要,继承详解,方法重写注意事项,方法重载与重写的区别,抽象类,代码块, 附重难点,代码实现源码,课堂笔记,课后扩展及答案
继承重点摘要 *继承的特点: 子类在初始化之前,一定要先完成父类数据的初始化 子类在初始化之前,一定要先访问父类构造,完成父类数据的初始化 系统在每一个构造方法中默认隐藏了一句super(); 如果我 ...
- 阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第6节 static静态_15_静态代码块
static的特殊用法, 静态代码块 加上构造方法,做测试 又创建一个对象 静态代码块 只执行一次 后续在学习jdbc的时候,静态代码块很有用途.
- Python基础学习Day6 is id == 区别,代码块,小数据池 ---->>编码
一.代码块 Python程序是由代码块构造的.块是一个python程序的文本,他是作为一个单元执行的. 代码块:一个模块,一个函数,一个类,一个文件等都是一个代码块. 而作为交互方式输入的每个命令都是 ...
- static{}静态代码块与{}普通代码块之间的区别
先看一个例子: //class A package com.my.test; class A { static { System.out.println("A1:父类静态代码区域" ...
- 5.1JAVA基础复习——JAVA中的静态代码块、构造代码块、构造函数、局部代码块区别
构造代码块: 在类中定义可以给所有对象进行初始化.局部代码块: 在方法中定义属性的生命周期.静态代码块: 在类中定义用于给类调用时属性的初始化 构造函数与构造代码块的区别: 构造函数是给对应的对象进行 ...
- java静态类、静态方法、静态代码块,静态变量及实例方法,实例变量初始化顺序及内存管理,机制
1.当一个类被第一次使用时,它需要被类加载器加载,而加载过程涉及以下两点: (1)在加载一个类时,如果它的父类还未被加载,那么其父类必须先被加载: (2)当类加载到内存之后,按照在代码中的出现顺序执行 ...
- final、static、代码块、静态代码块、内部类、代码执行顺序
final final域使得确保初始化安全性(initialization safety)成为可能,初始化安全性让不可变形对象不需要同步就能自由地被访问和共享 作用在类上 ...
- [Day13]static、final、匿名对象、内部类、包、修饰符、代码块
1.final-最终 (1)final的特点 final修饰类不可以被继承,但是可以继承其他类 final修饰的方法不可以被覆盖,但父类中没有final修饰方法,子类覆盖后可以加final final ...
随机推荐
- MAMP "403 Forbidden You don't have permission to access / on this server."
2015年01月22日 17:27:31 阅读数:3488 用MAMP搭建本地服务器的时候,设置好ip和端口等属性之后,浏览器访问,报 403错误: Forbidden You don't have ...
- Roslyn NameSyntax 的 ToString 和 ToFullString 的区别
本文告诉大家经常使用的 NameSyntax 拿到值的 ToString 和 ToFullString 方法的区别 从代码可以看到 NameSyntax 的 ToString 和 ToFullStri ...
- JavaScript DOM查询,原生js实现元素子节点的获取
在网页网页开发中,经常会需要获取某个网页元素的子元素,然后对其进行事件绑定.或样式修改等行为.这些操作对于jquery来说很容易,但是对于原生js会稍微麻烦一些,这里将介绍四种方法获取元素的子元素(本 ...
- javascript基础的一些总结
一 闭包 各种专业文献上的"闭包"(closure)定义非常抽象,很难看懂.我的理解是,闭包就是能够读取其他函数内部变量的函数. 由于在Javascript语言中,只有函数内部的子 ...
- 慕课网electron写音乐播放器教程,代码跟随教程变动(十)
添加播放状态,首先是歌曲名称和时间 在index.html中添加 <div class="container fixed-bottom bg-white pb-4"> ...
- java环境所遇问题
在javac能运行通过并且生成了.class文件但是java文件在运行时通不过出现上面图片情况,试了一上午发现我的和别人好像不一样,下面展示我的情况, 之前用户变量那里新建了一个classpath,不 ...
- while Ture怎么退出全部
while True: #这是一个死循环 如果想要quit出去只能一层一层的退出 比如如果在第三层输入quit会回到第二层 那么有什么方法能够在第三层就退出全部? print("level1 ...
- Linux中安装软件和各种常用命令
1.Centos7中安装mysql5.7的链接:http://blog.csdn.net/fanpeizhong/article/details/73557202 2.修改mysql默认密码的链接:h ...
- 7.13 Python基础语法
Python基础语法 编码: 默认情况下,Python 3 源码文件以 UTF-8 编码,所有字符串都是 unicode 字符串. 当然你也可以为源码文件指定不同的编码 python2.7中有两个函数 ...
- 【题解】NOIP2017逛公园(DP)
[题解]NOIP2017逛公园(DP) 第一次交挂了27分...我是不是必将惨败了... 考虑这样一种做法,设\(d_i\)表示从该节点到n节点的最短路径,\(dp(i,k)\)表示从\(i\)节点 ...