目录
1.final
主要用法有以下四种:
-
用来修饰数据:变量只能被赋值一次且它的值无法被改变。对于成员变量来讲,我们必须在声明时或者构造方法中对它赋值;
-
用来修饰方法参数:在变量的生存期中它的值不能被改变;
-
修饰方法:该方法无法被重写;(不常用)
-
修饰类:该类无法被继承extends。(不常用)
1.1修饰类
以下代码编译器直接报错
package finalstudy;
/**
* @author yuguang
* @date 2021/2/3 10:24
* @description
* todo final修饰类无法被继承
*/
public class TestFinal01 {
public static void main(String[] args) {
ManPeople man = new ManPeople();
System.out.println(man.getAge());
}
}
class ManPeople extends People {
}
final class People{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
1.2修饰方法
编译器报错
package finalstudy;
/**
* @author yuguang
* @date 2021/2/3 10:24
* @description todo final修饰方法无法被重写override
*/
public class TestFinal02 {
public static void main(String[] args) {
People man1 = new ManPeople();
System.out.println(man1.getNameAndAge());
ManPeople man = new ManPeople();
man.setAge(18);
man.setName("xixi");
System.out.println(man.getNameAndAge());
}
}
class ManPeople extends People {
@Override
public String getNameAndAge() {
return "不想告诉你";
}
}
class People {
private String name;
private int age;
public final String getNameAndAge() {
return name + " : " + age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
1.3修饰方法
编译器报错代码
package finalstudy;
/**
* @author yuguang
* @date 2021/2/3 10:24
* @description todo final修饰方法无法被重写,编译器直接报错
*/
public class TestFinal03 {
public static void main(String[] args) {
int age = 1;
System.out.println(age++);
System.out.println(++age);
People man1 = new ManPeople();
System.out.println(man1.getNameAndAge());
ManPeople man = new ManPeople();
man.setAge(18);
man.setName("xixi");
System.out.println(man.getNameAndAge());
System.out.println(man.testFinal(18, "xixi"));
}
}
class ManPeople extends People {
@Override
public String getNameAndAge() {
return "不想告诉你";
}
}
class People {
private String name;
private int age;
public String testFinal(final int age, final String name) {
name = "不告诉你";
age = 18;
return name + " : " + age;
}
//重载
public String testFinal(final String name, final int age) {
return name + " : " + age;
}
public String getNameAndAge() {
return name + " : " + age;
}
//重载
public final String getNameAndAge(String name) {
return name + " : " + age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
1.4修饰变量
package finalstudy;
/**
* @author yuguang
* @date 2021/2/3 10:24
* @description
* 包括成员变量和局部变量,该变量只能被赋值一次且它的值无法被改变。
* 对于成员变量来讲,我们必须在声明时或者构造方法中对它赋值;
*/
public class TestFinal04 {
private final String name = null;
private final int age;
public TestFinal04() {
age = 0;
}
public static void main(String[] args) {
//变量只能被赋值一次且它的值无法被改变
final int age;
age = 18;
System.out.println(age);
// age = 19; //报错
}
}
2.static
引入地址(https://www.cnblogs.com/adeng/p/6971366.html)
java中static关键字主要有两种作用:
第一:为某特定数据类型或对象分配单一的存储空间,而与创建对象的个数无关。
第二,实现某个方法或属性与类而不是对象关联在一起。
简单来说,在java语言中,static主要有5中使用情况:成员变量、成员方法、代码块,内部类和静态导包。
基本用法:
- static修饰成员变量:该成员变量属于类变量,可以通过 ClassName.attributeName 直接引用,而不需要new出类的实例。
- static修饰成员方法:该方法属于类的方法,可以通过 ClassName.methodName 直接引用,而不需要new出类的实例。
- static修饰代码块:仅在类初始化的时候执行一次,且加载顺序是严格按照类中静态资源的定义顺序来加载的;静态代码块对于定义在它之后的静态变量,可以赋值,但是不能访问。;父类代码块->子类代码块。
- static修饰内部类:static不能修饰普通类,只能修饰内部类,被static修饰的内部类的创建方式: new OuterClass.InnerClass()。
- static导入包:语法“import static java.lang.Math.*”,这样在类中就可以直接使用Math类中的静态方法而不需要写类名,个人认为,在频繁使用某个类的时候比较方便,但是降低了可读性。并且不建议导入*
2.1修饰成员变量
public class TestStatic02 {
public static void main(String[] args) {
System.out.println(People.description);
People.printDescription();
}
}
class People {
public static String description = "人";
public static void printDescription() {
System.out.println("输出介绍: "+description);
}
}
2.2修饰方法
public class TestStatic02 {
public static void main(String[] args) {
System.out.println(People.description);
People.printDescription();
}
}
class People {
public static String description = "人";
public static void printDescription() {
System.out.println("输出介绍: "+description);
}
}
2.3静态代码块
package study_static;
//初始化的顺序 静态代码块 > 构造代码块 > 构造函数
// 只需要进行一次的初始化操作都放在static代码块中进行。
public class TestStatic03 {
public static void main(String[] args) {
PersonWithStatic withStatic = new PersonWithStatic();
withStatic.setSexType(1);
System.out.println(withStatic.getSexText());
PersonNoStatic noStatic = new PersonNoStatic();
noStatic.setSexType(2);
System.out.println(noStatic.getSexText());
}
}
class PersonWithStatic {
private String sexText;
private Integer sexType;
//常量
private static String woman;
private static String man;
static {
man = "男";
woman = "女";
}
public String getSexText() {
if (sexType == 1) {
sexText = woman;
} else {
sexText = man;
}
return sexText;
}
public Integer getSexType() {
return sexType;
}
public void setSexType(Integer sexType) {
this.sexType = sexType;
}
public static String getWoman() {
return woman;
}
public static void setWoman(String woman) {
PersonWithStatic.woman = woman;
}
public static String getMan() {
return man;
}
public static void setMan(String man) {
PersonWithStatic.man = man;
}
}
class PersonNoStatic {
private String sexText;
private Integer sexType;
private static String woman = "女";
private static String man = "男";
public String getSexText() {
if (sexType == 1) {
sexText = woman;
} else {
sexText = man;
}
return sexText;
}
public void setSexText(String sexText) {
this.sexText = sexText;
}
public Integer getSexType() {
return sexType;
}
public void setSexType(Integer sexType) {
this.sexType = sexType;
}
public static String getWoman() {
return woman;
}
public static void setWoman(String woman) {
PersonNoStatic.woman = woman;
}
public static String getMan() {
return man;
}
public static void setMan(String man) {
PersonNoStatic.man = man;
}
}
2.4修饰内部类
static一般用来修饰成员变量或函数也修饰代码块,一般不能修饰类,只有内部类才可以,被修饰的内部类可以直接作为一个普通类来用,不需要创建一个外部类的实例,而普通内部类的引用需要创建一个外部类的实例。
package study_static;
public class TestStatic05 {
public static void main(String[] args) {
//非静态内部类需创建一个父类的实例,方能new
TestStatic05 father = new TestStatic05();
Inner inner = father.new Inner();
inner.print();
//静态内部类可以直接new
InnerStatic innerStatic = new InnerStatic();
innerStatic.print();
}
class Inner {
public void print() {
System.out.println("Inner");
}
}
static class InnerStatic {
public static void print() {
System.out.println("InnerStatic");
}
}
}
class Inner1 {
}
2.5static导入包
package study_static;
import static java.lang.Math.random;
import static java.lang.System.out;
/**
* @author yuguang
* @date 2021/2/4 9:28
* @description static 导入包
*/
public class TestStatic06 {
public static void main(String[] args) {
double random = Math.random();
out.println((int) (random * 10000));
//直接引入Math下面static方法
out.println(random());
out.println(random());
}
}
2.6static例子
2.6.1静态代码块
public class TestStatic04 {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> aClass = Class.forName("study_static.People1");
// System.out.println(People1.description);
// People1.printDescription();
}
}
class People1 {
//静态代码块
static {
System.out.println("People1 init ,static code");
}
//静态变量
public static String description = "人";
//静态方法
public static void printDescription() {
System.out.println("输出介绍: "+description);
}
//空构造方法
public People1() {
System.out.println("constructor");
}
}
2.6.2静态代码块和构造函数
静态代码块中:父>子
等级: 静态代码块>构造函数
package study_static;
public class demo2 extends Base {
static {
System.out.println("test static");
}
public demo2() {
System.out.println("test constructor");
}
public static void main(String[] args) {
new demo2();
}
}
class Base {
static {
System.out.println("base static");
}
public Base() {
System.out.println("base constructor");
}
}
2.6.3 面试题(继承、静态代码块、构造函数、成员变量)
在一个类中: 静态代码块 > 成员变量 > 构造函数
父 > 子:如父的 静态代码块、成员变量、构造函数 大于子的
package study_static;
/**
* 类似地,我们还是来想一下这段代码的具体执行过程。首
* 1-先加载Test类,因此会执行Test类中的static块。
* 2-接着执行new MyClass(),而MyClass类还没有被加载,因此需要加载MyClass类。在加载MyClass类的时候,
* 发现MyClass类继承自Test类,但是由于Test类已经被加载了,所以只需要加载MyClass类,那么就会执行MyClass类的中的static块。
* 在加载完之后,就通过构造器来生成对象。而在生成对象的时候,
* 3---必须先初始化父类的成员变量,因此会执行Test中的Person person = new Person(),
* 而Person类还没有被加载过,因此会先加载Person类并执行Person类中的static块,接着执行父类的构造器,完成了父类的初始化,
* 然后就来初始化自身了,因此会接着执行MyClass中的Person person = new Person(),最后执行MyClass的构造器。
*/
//todo 静态代码块存在内存中只加载一次
public class Test {
Person person = new Person("---4---Test");
static {
System.out.println("1---test static");
}
public Test() {
System.out.println("5----test constructor");
}
public static void main(String[] args) {
new MyClass();
}
}
class MyClass extends Test {
Person person = new Person("----6----MyClass");
static {
System.out.println("2----myclass static");
}
public MyClass() {
System.out.println("7----myclass constructor");
}
}
class Person {
static {
System.out.println("3----person static");
}
public Person(String str) {
System.out.println("person " + str);
}
}
2.6.4static代码块多个按照顺序执行
public class demo3 {
static{
System.out.println("test static 0");
}
static{
System.out.println("test static 1");
}
public static void main(String[] args) {
}
static{
System.out.println("test static 2");
}
static{
System.out.println("test static 3");
}
}
参考资料:
https://www.cnblogs.com/tonyluis/p/5582529.html