Java学习 day07_extends
2021/6/16 12:23:39
本文主要是介绍Java学习 day07_extends,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
匿名对象
什么是匿名(anonymous)对象?
-
没有名字的对象就是匿名对象
-
这个名字是引用类型变量名,也就是引用的名字
-
语法:就是创建一个对象,没有引用指向它
new 类名();
-
从实质上看,就是没有被栈上的引用指向,只孤零零的存在于堆上的对象就是匿名对象
匿名对象有啥用?
- a,可以用匿名对象作为方法的返回值
- b,作为对象调用方法
- c,可作为方法的实参传递给方法
// 几种用途演示 public class Demo { public static void main(String[] args) { //创建一个匿名对象 //new Student().method(); //new Student().method(); //new Student().method(); //new Student().method(); //new Student().method(); //new Student().method(); test(new Student()); } public static Student test() { /*Student s = new Student(); return s;*/ //上述步骤二合一 return new Student(); } public static void test(Student s){ s.method(); } } class Student { public void method() { System.out.println("Student"); } }
# 代码块(block)
代码块概念
- 在Java中,使用大括号”{}“括起来的代码被称为代码块,根据其位置和声明方式的不同,可以分为:
- 局部代码块
- 构造代码块
- 静态代码块
- 同步代码块(后边再说)
- 总体而言,代码块在实际开发中,使用频率并不高,可替代性也很强
- 但是由于其迷惑性极强,常年出没于各种面试题中
- 这个东西很绕,需要深入理解
局部代码块(local)
什么是局部代码块?
- 和局部变量位置相似,处在方法中局部位置的代码块,称之为局部代码块
- 声明方式:{}
- 位置:方法中的局部位置
- 代码执行顺序:从上到下
- 作用:限定局部变量的作用范围和生命周期,及早释放,提高内存利用率
- 实际用途:并没有多大用,不要在代码中使用局部代码块,早起Java程序员用来提高内存利用效率
构造代码块(building)
什么是构造代码块
- 和构造方法类似,处在类中成员位置的代码块,称之为构造代码块
- 声明:{}
- 位置:在类中成员位置
- 作用:构造代码块会随着构造器的执行而执行,不管是哪个构造器,也就是new对象的时候
总结一下到目前为止,我们给成员变量赋值的方式:
分情况讨论
1,创建对象的时候
- a,默认初始化
- b,显式赋值
- c,构造器
- d,构造代码块
2,创建对象之后
- a,对象名点去赋值
- b,成员方法给成员变量赋值
- new对象过程,构造代码块的执行顺序
- 对象创建出来后,就把所有成员变量的值默认初始化,然后开始其余赋值操作
- 如果构造器在第一行显式的调用了另一个构造器,那么程序先跳转到this构造器,但并不会执行
- 而是
- 按照类中定义代码块和成员变量的位置,从上到下执行代码块和成员变量自身的初始化语句
- 继而执行该this构造器代码
- 最后执行该构造器代码: 构造器一定是最后执行的
- 需要注意的是:
- 应该永远将构造代码块,放在成员变量的定义语句下面
- 一方面,如果代码块初始化在上,成员变量声明在下,逻辑上会很奇怪
- 另一方面,如果对象的创建依赖于代码块和成员变量的定义位置,很容易引发错误
- 可以使用this关键字,但是意义不大
- 应该永远将构造代码块,放在成员变量的定义语句下面
显式赋值和构造代码块,谁在代码书写顺序的上面,谁就先执行,反之在下面的要后执行
编译器在编译完代码后,实际上并不存在构造代码块的结构
编译器会智能的把显式赋值和构造代码块的代码,放入所有构造器的第一行,这么做:
1,为了保证变量都是先声明,再赋值
2,为了保证按照代码的书写顺序,从上到下执行显式赋值和构造代码块
- 写在书写顺序上面的就变成了显式赋值
- 写在书写顺序下面就跑到了构造器里面去了
3,为了保证构造代码块随着构造器的执行而执行(如果构造代码块中存在不是赋值语句的语句,会直接放入构造器的第一行)
package com.cskaoyan.building; public class Building { public static void main(String[] args) { C c = new C(88); } } class C{ { int a = 100; } int a = 99; public C(int a){ this.a = a; } } // 在编译后的代码中,a=99被放在了构造函数中
- 实践用途:
- 构造器只是创建某一个对象时调用的,但构造代码块却是创建该类每个对象都会调用的
- 因此,可以抽取出所有构造器都需要做的事情,放入构造代码块中
静态代码块
什么是静态代码块
- 使用static关键字修饰的构造代码块,处在类中的成员位置,称之为静态代码块
- 声明:static{}
- 位置:类中成员位置
- 作用:和静态成员一样,随着类加载而执行,一般用于给静态成员变量赋值,只执行一次
- new对象过程,静态代码块、构造代码块、构造方法的执行顺序
- 静态代码块
- 构造代码块
- 构造方法
- 需要注意的是:
- 静态代码块和静态成员一样,不能在里面调用非静态
- 除非是静态成员变量需要很复杂的初始化代码,否则没太大必要使用,直接显式赋值就行
- 静态代码块和静态成员变量的定义顺序,也会影响到静态成员变量的最终取值(谁在下面,谁后执行)
- 所以应该永远将静态代码块放在静态成员变量的定义下面
- 构造代码块可以给静态成员变量赋值,静态代码块却不能给普通成员代码块赋值
- 若构造代码块和静态代码块同时给一个静态成员变量赋值
- 它们在代码中的顺序,并不会对结果造成影响
- 因为静态代码块总是先于构造代码块执行
- 若构造代码块和静态代码块同时给一个静态成员变量赋值
一些实际的使用案例
- 构造代码块使用场景:
- 不想让对象共享一个属性(static),但是还需要对象的某个属性具有相同初始值。
- 比如公司新来了一批员工,他们的初始薪资一样,但是后面会根据表现调薪
- 这个时候如果用static,显然不合适,因为调薪是针对个人的
- 使用普通的成员变量定义薪资,然后用构造代码块给变量赋值
- 静态代码块的经典使用场景:
- 复杂的静态变量初始化
- JDBC的驱动加载(Java EE学)
一定会触发类加载的几种情况
- 执行某个类的main方法,一定会进行类加载
- 创建某个类的对象,一定会进行类加载
- 访问某个类的静态成员,一定会进行类加载
牛刀小试
查看以下代码,请回答程序运行的结果
public class ExerciseBlock { // 2.静态代码块在类加载时执行,输出第一个 static { System.out.println("main方法静态代码块!"); } { System.out.println("main方法构造代码块!"); } // 1.程序的入口,但是要先去进行所在类的类加载 public static void main(String[] args) { // 3.回来执行main方法,输出main方法开始执行! System.out.println("main方法开始执行!"); Star s = new Star(8,"马化腾"); //6.按照顺序,Star.name是刘亦菲 System.out.println(Star.name); // 7. s.age就是传递的参数,也就是8 System.out.println(s.age); } } class Star{ { age = 18; Star.name = "杨超越"; System.out.println("我喜欢杨超越"); } // 4.main方法创建了star对象,先处理static修饰的,static代码块输出我喜欢杨幂 static String name = "王菲"; int age = 28; static { name = "杨幂"; System.out.println("我喜欢杨幂"); } // 5.创建对象使用这个构造器,在里面调用下面的构造器,不过还是先执行构造代码块里的东西 // 所以输出我喜欢杨超越,age和age,name public Star(int age,String name) { this(age); System.out.println("age,name:构造器!"); Star.name = name; Star.name = "刘亦菲"; } public Star(int age) { System.out.println("age:构造器!"); this.age = age; } public Star() { } }
- 程序的打印结果应该什么呢?
package和import关键字
package和import两个关键字涉及到了一个Java文件中的包的操作
package
作用?
-
在Java源文件的第一行,使用package关键字声明
- 声明该Java源文件中,所定义的所有类,都属于同一个包
- 一个Java源文件,只能有一个public修饰的类
- package关键字后,跟上当前类的包名,表示所处的包
- 声明该Java源文件中,所定义的所有类,都属于同一个包
-
语法
-
package 包名;
-
-
注意
- 包名的书写,用逗号隔开
- 语法上,该声明语句一定位于一个Java源文件的有效代码的第一行,否则会报错
- 注释不算有效代码,你可以把package声明放在注释下面
- 但是根据规范,不要这么做
- 应该将package永远放在Java源文件真正意义的第一行
- 3,如果一个class直接放在src目录根目录,它就无需包声明
全限定类名
什么是全限定类名?
- 可以唯一确定一个类的,由包名加上类名组成的字符串
- 不做任何操作的情况下,直接输出一个类的对象,会打印全限定类名
- 例如:com.cskaoyan.oop.statickeyword.Star
import
引例
- 在包名为onepackage的包中创建一个Student类
- 在包名为anotherpackage的包中创建一个同名Student类
- 在onepackage包下,写一个测试类Test
- 在测试类Test中,创建anotherpackage包中Student类的对象
显然编译器会默认优先搜索同包下的,Student类,然后去创建它的对象
为了让编译器,去获取到不同包下的,Student类,必须由程序员显式的告诉编译器怎么去找到这个类
有两种解决方法
-
在创建类的对象的语句中,不使用简单的类名,而是使用全限定类名
- 不可能真的这么做,因为全限定类名太长了
-
使用import关键字,声明要使用的类
-
语法
-
import 全限定类名;
-
-
语法上import关键字应该放在,package声明语句和类声明语句之间
-
和package关键字一样,import声明应该永远紧跟在package声明之后(规范)
-
import声明提供了一种包的智能导入方式,语法为
-
import <包名>.*;
-
包中的类将根据需要导入,避免使用多条import声明
-
需要注意的是,如果本包中已存在同名类,就判定为不需要导包,.*就不会自动导包,只有在不导包就会报错的情况下,才会使用到智能导包
-
-
-
Java语言核心包java.lang包中的类将被隐式导入,可以直接使用其中的类
-
import java.lang.*;
-
我们使用的String、Integer、System都属于这个包
-
-
-
静态导入
-
语法
-
import static 全限定类名.*; import static 全限定类名.静态成员;
-
-
可以用来导入静态方法和静态成员变量
-
以往我们调用不同包的静态成员,通过类名.成员名访问,如果静态导入,可以省略类名
-
例如
-
import static java.lang.System.*;
-
可以这样写输出语句
out.println("Hello World!");
-
import static java.lang.Math.*;
-
可以这样使用
double pi = PI; double result = pow(2,3);
-
-
-
实践开发中,static导入很少使用,了解认识即可
如果不同包下两个同名类,我都想使用咋办?
- 真的存在这种需求,建议改名一个
- 一个用全限定类名去使用
这篇关于Java学习 day07_extends的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-24Java中定时任务实现方式及源码剖析
- 2024-11-24Java中定时任务实现方式及源码剖析
- 2024-11-24鸿蒙原生开发手记:03-元服务开发全流程(开发元服务,只需要看这一篇文章)
- 2024-11-24细说敏捷:敏捷四会之每日站会
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解