创建一个子类时(继承关系),他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序
① 父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
② 子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
③ 父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
④ 父类的构造方法
⑤ 子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
⑥ 子类的构造方法
代码:
package com.atguigu.day15;
public class CodeBlockExam {
public static void main(String[] args) {
//System.out.println(Person1.total);101
//System.out.println(Person1.total);101
C02 c02 = new C02();
}
}
class Person1 {
public static int total = 100;
static {
total++;
System.out.println("in static block");
}
}
class A02 {
private static int n1 = getVal01();
static {
System.out.println("A02的一个静态代码块..");
}
{
System.out.println("A02的第一个普通代码块..");
}
public int n3 = getVal02();
public static int getVal01() {
System.out.println("getVal01");
return 10;
}
public int getVal02() {
System.out.println("getVal02");
return 10;
}
public A02() {
System.out.println("A02的构造器");
}
}
class B02 extends A02 {
private static int n3 = getVal03();
static {
System.out.println("B02的一个静态代码块..");
}
public int n5 = getVal04();
{
System.out.println("B02的第一个普通代码块..");
}
public static int getVal03() {
System.out.println("getVal03");
return 10;
}
public int getVal04() {
System.out.println("getVal04");
return 10;
}
public B02() {
System.out.println("B02的构造器");
// TODO Auto-generated constructor stub
}
}
class C02 extends B02 {
private static int n6 = getVal06();
static {
System.out.println("C02的一个静态代码块..");
}
{
System.out.println("C02的第一个普通代码块..");
}
public int n8 = getVal08();
public static int getVal06() {
System.out.println("getVal06");
return 10;
}
public int getVal08() {
System.out.println("getVal08");
return 10;
}
public C02() {
System.out.println("C02的构造器");
}
}
设计模式
设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式 。
设计模式就像是经典的棋谱,不同的棋局,我们用不同的棋谱,免去我们自己再思考和摸索。”套路”
单例模式
1) 饿汉式
package com.atguigu.day15;
public class SingleTonDemo {
public static void main(String[] args) {
Dog1 dog1 = Dog1.getInstance();
Dog1 dog2 = Dog1.getInstance();
//dog1 和 dog2 是同一个狗..
System.out.println(dog1.hashCode() + " " + dog2.hashCode());
}
}
//需求
//1. 在整个程序中,只能有一个Dog 的对象实例
//2. 就是饿汉式
//3. 在没有使用dog 前,就创建好 , 就称为饿汉式.
class Dog{
private String name;
private static Dog dog = new Dog("哈士奇");
//将构造器私有化
private Dog(String name){
this.name = name;
}
public static Dog getInstance(){
return dog;
}
}
2)懒汉式
public class SingleTonDemo {
public static void main(String[] args) {
Cat1 cat1 = Cat1.getInstance("小红");
Cat1 cat2 = Cat1.getInstance("小白");
System.out.println("cat1.hashcode=" + cat1.hashCode());
System.out.println("cat2.hashcode=" + cat2.hashCode());
System.out.println(cat1.getName());
System.out.println(cat2.getName());
}
}
//懒汉式
//1. 在整个程序中,只能有一个Cat 的对象实例
//2. 懒汉式
//3. 在调用 getInstance方法时,才会创建cat对象,所以称为懒汉式
class Cat1{
private String name;
private static Cat1 cat = null;//初始化null
private Cat1(String name){ //构造器私有化
this.name = name;
}
//公开静态方法.
public static Cat1 getInstance(String name) {
if(cat == null) {//说明你还没有创建
cat = new Cat1(name);
}
return cat;
}
public String getName() {
return this.name;
}
}
final初始化赋值的位置
class AAAAA{
//final 在定义是赋值
public final double TAX_RATE=0.08;
public final double TAX_RATE2;
public final double TAX_RATE3;
//对静态的final 属性可以在定义时,赋值
public static final double TAX_RATE4 = 0.01;
public static final double TAX_RATE5 ;
static {
//对静态的final 属性可以在静态代码块赋值
TAX_RATE5 = 0.2;
//TAX_RATE3 = 0.1;
}
{
//在代码块给final属性赋值.
TAX_RATE3 = 0.1;
}
public AAAAA() {
//在构造器给final属性赋值
TAX_RATE2 = 0.09;
}
}
自定义枚举
package com.atguigu.day17;
public class EnumerationDemo01 {
public static void main(String[] args) {
System.out.println(Season.SPRING);
System.out.println(Season.SUMMER);
}
}
/*
* 不需要提供setXxx 方法,因为枚举对象通常为只读
对枚举对象/属性使用 final + static 共同修饰,实现底层优化.
枚举对象名通常使用全部大写,常量的命名规范.
枚举对象根据需要,也可以有多个属性
*/
class Season { // 自定义枚举
private String name; //属性
private String desc; //属性,描述季节
public String getName(){
return name;
}
private Season(String name){
this.name = name;
}
private Season(String name, String desc) {
super();
this.name = name;
this.desc = desc;
}
//提供一组常量,直接使用static
public final static Season SUMMER = new Season("夏天","炎热");
public final static Season AUTUMN = new Season("秋天");
public final static Season SPRING = new Season("春天");
public final static Season WINTER = new Season("冬天");
@Override
public String toString() {
return "Season [name=" + name + ", desc=" + desc + "]";
}
}
enum关键字实现枚举
package com.atguigu.day17;
public class EnumerationDemo02 {
public static void main(String[] args) {
//说明
//1.当我们直接输出枚举值时,输出的是常量名
//2. 因为 Enum 重写了 Object 的 toString
System.out.println(Season2.AUTUMN);
}
}
//这里有一些规范,需要遵守
//1. 需要将常量 (枚举值) 写在枚举的最前面
//2. 如果有多个常量(枚举值), 使用, 隔开,然后使用; 结尾
//3. SPRING("春天", "暖和") 表示含义是,调用 构造器 Season2(String name, String desc)
//4. SPRING("春天", "暖和"), 完整的写法是==>public final static SPRING => 底层反编译.
//5. 当使用 enum 关键字后 Season2, 默认会继承 枚举类,因此可以使用继承的方法
enum Season2 {
/*
season反编译 结果(被final修饰,)
D:\eclipse\AtGuiGu\bin\com\atguigu\day17>javap -p Season2.class
Compiled from "EnumerationDemo02.java"
final class com.atguigu.day17.Season2 extends java.lang.Enum<com.atguigu.day17.Season2> {
public static final com.atguigu.day17.Season2 SPRING;
public static final com.atguigu.day17.Season2 WINTER;
public static final com.atguigu.day17.Season2 SUMMER;
public static final com.atguigu.day17.Season2 AUTUMN;
private java.lang.String name;
private java.lang.String desc;
private static final com.atguigu.day17.Season2[] ENUM$VALUES;
static {};
private com.atguigu.day17.Season2(java.lang.String, int, java.lang.String, java.lang.String);
public java.lang.String getName();
public java.lang.String getDesc();
public java.lang.String toString();
public static com.atguigu.day17.Season2[] values();
public static com.atguigu.day17.Season2 valueOf(java.lang.String);
*/
SPRING("春天", "暖和"), //SPRING 表示 public final static SPRING = new Season2()
WINTER("冬天", "寒冷"),
SUMMER("夏天", "炎热"),
AUTUMN("秋天", "凉爽");
private String name;
private String desc;
private Season2(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
//使用快捷键不好使
public String toString(){
return "信息如下:name=" + name + " desc=" + desc;
}
}
Enum类的方法练习
package com.atguigu.day17;
public class EnumerationMethod {
public static void main(String[] args) {
// 说明
// 1.当我们直接输出枚举值时,输出的是常量名
// 2. 因为 Enum 重写了 Object 的 toString
System.out.println(Season3.AUTUMN);
//name
System.out.println(Season3.AUTUMN.name()); // AUTUMN
// ordinal方法
System.out.println(Season3.SPRING.ordinal()); // 0
// values
Season3[] values = Season3.values();
// 增强for
for (Season3 season : values) {
System.out.println(season);
}
//valueOf
System.out.println("===valueof====");
//思考:看到当我们的名字错误时,程序就退出..==> 异常处理
Season3 mySeason = Season3.valueOf("SUMMER");
System.out.println(mySeason);
//compareTo
/*
* public final int compareTo(E o) {
Enum<?> other = (Enum<?>)o;
Enum<E> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
解读:
将两个常量的位置的值比较 self.ordinal - other.ordinal
(1) 如果是 0, 表示两个是相等的
(2) 如果不是0, 表示不等.
*/
//Season3.AUTUMN 序列号 3 Season3.SPRING 序列号 0
System.out.println(Season3.SPRING.compareTo(Season3.SUMMER)); //-2
if(Season3.SPRING.compareTo(Season3.SPRING) == 0) {
System.out.println("相等");
} else {
System.out.println("不相等");
}
}
}
/*
*
* toString:Enum类已经重写过了,返回的是当前对象 名,子类可以重写该方法,用于返回对象的属性信息
* name:返回当前对象名(常量名),子类中不能重写
* ordinal:返回当前对象的位置号,默认从0开始
* values:返回当前枚举类中所有的常量
* valueOf:将字符串转换成枚举对象,要求字符串必须 为已有的常量名,否则报异常!
* compareTo:比较两个枚举常量,比较的就是位置号!
*
*/
enum Season3 {
SPRING("春天", "暖和"), // 0
WINTER("冬天", "寒冷"), // 1
SUMMER("夏天", "炎热"), // 2
AUTUMN("秋天", "凉爽"); // 3
private String name;
private String desc;
private Season3(String name, String desc) {
this.name = name;
this.desc = desc;
}
private Season3(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
public String toString() {
return "信息如下: name =" + name + " desc=" + desc;
}
}
enum实现接口
package com.atguigu.day17;
public class EnumerationImplements {
public static void main(String[] args) {
State.PLAYING.ring();
State.STOP.show();
}
}
interface Sound { // 接口
void ring();
}
interface Display { // 接口
void show();
}
enum State implements Display, Sound {
// 写出枚举常量(值)
// 1.这里当枚举实现接口时,可以再本类中去实现接口的方法
// ,还支持在枚举常量(值) 也去实现接口的方法
// 2.当枚举类实现了某个方法,同时枚举常量也实现相同的方法,则
// 以 枚举常量 实现的方法为准,可以通过java的动态绑定机制理解
// 3.在枚举常量 实现方法中,用super调用的 是本类中实现的方法
PLAYING("hello a"){
@Override
public void ring() {
System.out.println("PLAYING 中的 ring方法");
}
@Override
public void show() {
System.out.println("PLAYING 中的 show方法");
}
},
STOP("停止了"){
@Override
public void ring() {
System.out.println("STOP 中的 ring方法");
}
@Override
public void show() {
// TODO Auto-generated method stub
super.show();
System.out.println("STOP 中的 show方法");
}
};
@Override
public void ring() {
System.out.println("ring 重写了");
}
@Override
public void show() {
System.out.println("show 重写了");
}
//属性
private String value;
//构造器
private State(String value){
this.value = value;
}
}
自定义注解
package com.atguigu.day17;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//静态引入..
import static java.lang.annotation.ElementType.*; //引入 ElementType
public class MyAnnotationDemo {
}
@MyAnn
class Doctor {
//表示我通过注解,入参给 MyAnn
//如果开发自定义注解,可以根据入参,进行处理(高级)=> 自己写框架,反射
//一般自己开发自定义注解很少,但是使用却是很多, 框架
@MyAnn(value="hello", name = {"ok", "yes", "abc"})
public void cry() {
}
}
/*
* 解读
* 1. MyAnn 是一个注解类 因为 @interface
* 2. @Target 表示MyAnn 可以使用在 TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE
* 3. @Documented 表示 MyAnn 在文档javadoc 会生效
* 4. @Retention 表示作用范围在 RUNTIME 级别
* 5. String value() default "bb"; 表示 :MyAnn 注解 有 value 可以赋值, 默认为 bb
* 6. String[] name() default "kk"; 表示:MyAnn 注解 有 name, 可以赋值,同时可以按照String[]给值
7. 写的这个注解因为没有编译器底层支持,语法通过
*/
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Deprecated
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnn{
String value() default "bb";
String[] name() default "aa";
}
包的静态导入
package com.atguigu.day17;
public class MyTools {
//静态属性
public static String name = "我的工具类";
public static void cal(){
System.out.println("计算~~~");
}
}
使用静态导入可以使被导入类的静态变量和静态方法在当前类直接可见,使用这些静态成员无需再给出他们的类名
package com.atguigu.day17.homework;
//传统导包
//import com.atguigu.day17.MyTools;
//静态导入
//表示将 MyTools 类的静态成员引入. 表示使用静态成员时,不要带类名
import static com.atguigu.day17.MyTools.*;
public class UseMyTools {
public static void main(String[] args) {
//System.out.println(MyTools.name);
cal();
}
}