java学习基础课之面向对象(渡一教育)【修饰符】(六)

2023-12-16 20:20

本文主要是介绍java学习基础课之面向对象(渡一教育)【修饰符】(六),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 一、权限修饰符
    • 二、特征修饰符
      • 1. final
      • 2. static
    • 三、设计模式
    • 四、单例模式(Singleton)
    • 五、存在继承关系的类 加载机制 及执行过程
    • 六、native
    • 七、abstract
    • 八、接口

修饰符

权限修饰符
public 公共的
protected 受保护的
默认不写 默认的
private 私有的

特征修饰符
final 最终的 不可更改的
static 静态的
abstract 抽象的
native 本地的
transient 瞬时的 短暂的------>序列化
synchronized 同步的 线程问题
volatile 不稳定的

一、权限修饰符

public      公共的  本类   同包   子类   当前项目中任意类的位置只要有对象都可以访问
protected	保护的	本类   同包   子类(通过子类对象在子类范围内部访问)
默认不写	    默认的	本类   同包
private	    私有的	本类   

可以修饰类及类成员(除了块)
修饰类的时候只允许两个 public , 默认不写

新建一个包packa
packa中定义一个类TestA:

package packa;public class TestA {public static void main(String[] args){TestA ta = new TestA();ta.testPublic();ta.testProtected();ta.testDefault();ta.testPrivate();}//四个修饰符在本类中都可以访问public void testPublic(){System.out.println("我是TestA类中的public修饰符方法");}protected void testProtected(){System.out.println("我是TestA类中的protected修饰符方法");}void testDefault(){System.out.println("我是TestA类中的默认不写修饰符方法");}private void testPrivate(){System.out.println("我是TestA类中的private修饰符方法");}}

四个修饰赋在本类中都可以访问。

同一个包中,再定义一个新的类TestAA:

package packa;
//把TestA中的主方法,放在TestAA中,测试四个修饰符的访问权限。
public class TestAA {public static void main(String[] args){TestA ta = new TestA();ta.testPublic();ta.testProtected();ta.testDefault();//ta.testPrivate();//报错,这是私有的,只能在本类中被访问}
}

私有的修饰符,只能在本类中被访问。其他三个在同包中都可以访问。

在packa中再建立一个包,inner
inner中在建立一个新的类,TestInnerA:

package packa.innera;import packa.TestA;public class TestInnerA {public static void main(String[] args){TestA ta = new TestA();ta.testPublic();//ta.testProtected();  //不好用,报错//ta.testDefault();//不好用,报错//ta.testPrivate();//不好用,报错,私有的}//说明和packa不是同包。
}

TestA和TestInnerA不是同一个包。package 后面的名字不一样,就不是一个包。

新建一个包,packb,这个包和packa并列。
packb中建立一个TestB:

package packb;
import packa.TestA;public class TestB extends TestA{ //TestB是TestA的子类,所以在这个子类范围内可以访问TestA的成员public void testB(){this.testPublic();//子类可以访问父类的共有方法this.testProtected();//子类可以访问父类的保护方法}public static void main(String[] args){TestB tb = new TestB();tb.testPublic();//可以调用。子类可以访问父类的共有方法tb.testProtected();//通过继承,可以调用。子类可以访问父类的保护方法TestA ta = new TestA();ta.testPublic();//  ta.testProtected();//报错!继承的子类TestB可以访问保护成员,自己却不能访问保护成员。//因为保护成员,只能在本类,同包和子类(通过子类对象在子类范围内部访问)中访问,你这个不是子类对象,也不是本类,不是同包。}
}
//但是一旦出了TestB这个子类的范围,就会报错。比如,你将主方法放在子类的外面,类似下面注释那样,就会报错。

但是一旦出了TestB这个子类的范围,就会报错。比如,你将主方法放在子类的外面,类似下面注释那样,就会报错。

package test;import packb.TestB;public class TestMain {public static void main(String[] args){TestB tb = new TestB();tb.testPublic();//tb.testProtected();//报错,因为不在子类的范围内了。}
}

保护成员只能在本类,同包和子类(通过子类对象在子类范围内部访问)中访问。本类和同包比较容易理解,主要这个子类,重点一:是子类的对象。重点二:是子类范围内部。

私有成员的好处,控制你的输入,不会让你随便修改属性的值,而且可以通过方法判断你给的值,是否合适。例子如下:

package person;public class Person {//属性public String name;private int age;public String sex;//方法//设计一个方法  用来取得age属性的值//   提供条件?不需要   返回值? 获取的age的值public int getAge(){//ifreturn this.age;}//设计一个方法  用来给age属性赋值//   提供条件?  age的值    返回值?voidpublic void setAge(int age){if(age<0){System.out.println("对不起 您还没出生呢 请给正确的年龄范围");this.age = -1000;//抛出异常}else if(age>130){System.out.println("对不起 您已经升仙啦 请给正确的年龄范围");this.age = -1000;//抛出异常}else {this.age = age;}}
}

主方法:

package person;public class Test {public static void main(String[] args){//创建类的过程是在Java中描述的过程//1.创建对象Person p = new Person();//2.对象的引用 . 调用属性p.name = "郑中拓";p.setAge(18);  //如果设置的值不合理,会提醒你的。你也不能随意设置不合理的值了。p.sex = "男";System.out.println("今年"+p.getAge());
//以前可以通过p.age直接访问属性了,
//但是由于我们把属性设置成了私有的,所以需要方法进行访问了。}
}

Java类和类之间的关系
继承 关联 依赖
Java面向对象的四个特征
继承 封装 多态 (抽象)

封装 : 将一些数据或执行过程 进行一个包装
目的 : 保护这些数据 或 执行过程的安全

  • 对属性本身的封装:
    属性私有(封装在类中)
    提供操作属性相应的方式(公有的方法)
  • 以后强烈建议大家属性不要公有的---->非常不安全
  • 既然以后大家都这样操作属性 , 属性及其操作属性的方法都有其命名的规约
    age------> setAge getAge
    myAge–> setMyAge getMyAge

二、特征修饰符

1. final

1.可以修饰什么
2.修饰以后有什么特点

  • 修饰变量
  • 修饰属性
  • 修饰方法
  • 修饰类本身
  1. 修饰变量
  • 如果在定义变量时没有赋初始值,给变量一次存值的机会(因为变量在栈内存空间内 没有默认值 如果不给机会 就没法用啦)
  • 一旦变量被存储了一个值, 若用final修饰后 则不让再次改变 ----> 相当于常量啦(值没法动)
package test_final;public class TestFinal {public static void main(String[] args){final int a = 1;//声明变量   内存开辟栈内存空间//上面那一句也可以写成下面的两行/* final int a ;a = 1;*///如果在定义变量时没有赋初始值//给变量一次存值的机会(因为变量在栈内存空间内 没有默认值 如果不给机会 就没法用啦)a = 10;//报错//一旦变量被存储了一个值 若用final修饰后 则不让再次改变 ----> 相当于常量啦(值没法动)}
}
  • 注意变量类型是基本类型还是引用类型
  • 如果修饰的变量是基本数据类型,则变量内的值不让更改—常量
  • 如果修饰的变量是引用数据类型 ,则变量内的地址引用不让更改—对象唯一
package test_final;public class TestFinal {final int[] x;x = new int[]{1,2,3};x[0] = 10;x[0] = 100;//不报错!因为我们改的是栈内存里的值,而不是改了x的地址// x = new int[5];//这就会报错。因为试图修改引用的地址,肯定报错。}
}
  1. 修饰属性
  • 全局变量,存储在堆内存的对象空间内一个空间
  • 属性如果没有赋值 ,有默认值存在的,所以,属性用final修饰后,必须给属性赋初值,否则编译报错private final String name = "";空值都行,但是必须给初值。
  • 特点与修饰变量一致
    注意变量类型是基本类型还是引用类型
    如果修饰的变量是基本数据类型 ,则变量内的值不让更改—常量
    如果修饰的变量是引用数据类型 ,则变量内的地址引用不让更改—对象唯一
  1. 修饰方法
    方法是最终的方法,不可更改。
    子类继承父类的方法 , 将父类的方法重写(覆盖)
  • final修饰的方法 ,要求不可以被子类重写(覆盖)。
    父类:
package test_final;public class Animal {public void eat(){System.out.println("动物的吃饭方法");}
}

子类:

package test_final;public class Person extends Animal{//extends-->扩展public void eat(){System.out.println("子类重写(覆盖)父类的吃饭方法");}
}

主方法:

package test_final;public class TestFinal {public static void main(String[] args){Person p = new Person();p.eat();}
}
//这是测试重写,完全没有问题。

但是一旦我将父类的方法,利用final修饰,子类就不可以重写了。

package test_final;public class Animal {public final void eat(){System.out.println("动物的吃饭方法");}
}

子类重写eat时会报错的。

package test_final;public class Person extends Animal{//报错!不可以重写。public void eat(){System.out.println("子类重写(覆盖)父类的吃饭方法");}
}
  1. 修饰类本身
  • 类是最终的 ,不可以更改
  • (太监类 无后) 此类不可以被其他子类继承
  • 通常都是一些定义好的工具类
    Math Scanner Integer String

2. static

1.可以修饰什么
2.修饰后有什么特点

1.可以修饰 :

  • 修饰属性
  • 修饰方法
  • 修饰块
  • 修饰类(内部类)
  1. 特点:
  • (1)静态元素在类加载时就初始化啦,创建的非常早,此时没有创建对象
  • (2)静态元素存储在静态元素区中,每一个类有一个自己的区域,与别的类不冲突
  • (3)静态元素只加载一次(只有一份),全部类对象及类本身共享
  • (4)由于静态元素区加载的时候,有可能没有创建对象,可以通过类名字直接访问
  • (5)可以理解为静态元素不属于任何一个对象,属于类的
  • (6)内存管理,栈内存创建开始用完即回收,堆内存通过GC回收。静态元素区Garbage Collection无法管理,可以粗暴的认为常驻内存
  • (7)非静态成员(堆内存对象里)中可以访问静态成员(静态区)
  • (8)静态成员中可以访问静态成员(都存在静态区)
  • (9)静态成员中不可以访问非静态成员(个数 一个出发访问一堆相同名字的东西 说不清)(静态元素属于类 非静态成员属于对象自己)
  • (10)静态元素中不可以出现this或super关键字(静态元素属于类,不属于对象,所以this和super就说不清楚了。)

不用static的代码:

public class Person {public String name;  //暂时用public讲,方便。实际最好设置为私有的。public int age;//斜体public static void main(String[] args){Person p1 = new Person();p1.name = "阿拓小哥哥";p1.age = 18;Person p2 = new Person();// p2 =p1;//如果加上这句话,两个输出都是:姬成小姐姐了。p2.name = "姬成小姐姐";p2.age = 16;//第二个对象使用的age就是第一个对象的ageSystem.out.println(p1.name+"今年"+p1.age+"岁");System.out.println(p2.name+"今年"+p2.age+"岁");}
}
//输出结果:
//阿拓小哥哥今年18岁
//姬成小姐姐今年16岁
// p2 =p1;//如果加上这句话,两个输出都是:姬成小姐姐今年16岁

加上static以后:

//age加上了static特征修饰符
public class Person {public String name;  //暂时用public讲,方便。实际最好设置为私有的。public  static int age;//斜体public void test(){System.out.println("我是普通方法"+Person.age); //非静态方法可以访问静态成员}public static void testStatic(){System.out.println("我是静态方法");}	 //静态方法可以访问静态成员    //但是不可以访问非静态成员,因为一个静态方法,对应着好多的对象,不知道访问哪一个对象的成员了。public static void main(String[] args){Person p1 = new Person();p1.name = "阿拓小哥哥";p1.age = 18;Person p2 = new Person();p2.name = "姬成小姐姐";p2.age = 16;//第二个对象使用的age就是第一个对象的ageSystem.out.println(p1.name+"今年"+p1.age+"岁");System.out.println(p2.name+"今年"+p2.age+"岁");}
}
//结果:
//阿拓小哥哥今年16岁  ???为什么是16岁呢??
//姬成小姐姐今年16岁
//原因只可能是:第二个对象使用的age就是第一个对象的age

那么static修饰的存在哪了呢??实际上存在了静态元素区。
age存在了静态元素区。

在这里插入图片描述

  • 小任务
    书店买书
    按照买书人的身份做相应的折扣
    1.书店内部人员 管理员 5折-------0
    2.书店的VIP VIP会员 8折-------1
    3.普通路人 普通 全价-------2
package bookstroe;/**书店类*/
public class BookStore {private static final int BOOKSTROE_ADMIN = 0;private static final int BOOKSTROE_VIP = 1;private static final int BOOKSTROE_NORMAL = 2;
//为什么加static?是因为用了static,就不用创建对象,通过类名字就可以直接访问了,BookStore.BOOKSTROE_ADMIN
//为什么加final?为了让这个变量值不再改变了。public void buyBook(float price,int identity){switch(identity){case BookStore.BOOKSTROE_ADMIN:System.out.println("尊敬的书店管理员,您购买的图书应付款:"+price*0.5);break;case BookStore.BOOKSTROE_VIP:System.out.println("尊敬的书店VIP客户,您购买的图书应付款:"+price*0.8);break;case BookStore.BOOKSTROE_NORMAL:System.out.println("尊敬的普通用户,您购买的图书应付款:"+price);break;default:System.out.println("对不起,系统查不到您的身份,不许买书");}}
}
package bookstroe;import java.util.Scanner;public class TestMain {public static void main(String[] args){BookStore bookStore = new BookStore();Scanner input = new Scanner(System.in);System.out.println("请输入图书金额");float price = input.nextFloat();System.out.println("请出示您的身份");int identity = input.nextInt();bookStore.buyBook(price,identity);}
}

命名规约
类名首字母大写
属性 方法 变量首字母小写 第二个大写
构造方法 与类名一致 首字母大写
包 全部字母小写 注意区分关键字
静态常量 全部字母大写 _
私有属性对应的方法 getName/setName
见名知义

三、设计模式

设计模式 23种 (内功心法)

设计模式不是知识点;
设计模式是一种设计经验的总结;
设计模式用来解决某些场景下的某一类问题的---->通用的解决方案;
有了设计模式之后 可以让代码更容易被理解 确保了复用性 可靠性 可扩展性。

设计模式分为三类

  • 1.创建型模式(5种)----->用于解决对象创建的过程
    单例模式;工厂方法模式;抽象工厂模式;建造者模式; 原型模式
  • 2.结构型模式(7种)----->把类或对象通过某种形式结合在一起 构成某种复杂或合理的结构
    适配器模式;装饰者模式 ;代理模式;外观模式;桥接模式 组合模式;享元模式
  • 3.行为型模式(11种)---->用来解决类或对象之间的交互 更合理的优化类或对象之间的关系
    观察者模式 ;策略模式;模板模式;责任链模式; 解析器模式 ;迭代子模式
    命令模式;状态模式;备忘录模式; 访问者模式; 中介者模式

四、单例模式(Singleton)

设计–>一个类只能创建一个对象,有效减少内存占用空间
设计一个系统—>百度 搜索引擎

public class Baidu{public void 搜索(String keyword){}}

创建一个Baidu对象 new
调用搜索的方法 , 做事情 , 方法执行一遍
问题
同一时间有很多很多很多很多人在使用这个系统
解决方法
对象—>只创建一个 , 堆内存中就只开辟一个空间
调用一次方法—>临时执行一次 方法执行空间就回收啦

五、存在继承关系的类 加载机制 及执行过程

父类:

package test;public class Animal {public String test = "AnimalField";public static String testStatic = "AnimalStaticField";public Animal(){System.out.println("我是animal中默认无参数的构造方法");}{this.test(); //块中调用了普通方法System.out.println("我是animal中的普通代码块"+test);}static{Animal.testStatic();System.out.println("我是animal中的静态代码块"+testStatic);}public void test(){System.out.println("我是animal类中的普通方法");}public static void testStatic(){System.out.println("我是animal类中的静态方法");}
}

子类:

package test;public class Person extends Animal{public String test = "personField";public static String testStatic = "personStaticField";public Person(){//super();//默认调用父类无参数的构造方法System.out.println("我是person中默认无参数的构造方法");}{this.testPerson(); //调用了普通方法System.out.println("我是person中的普通代码块"+test);}static{Person.testStatic();System.out.println("我是person中的静态代码块"+testStatic);}public void testPerson(){System.out.println("我是person类中的普通方法");}public static void testStatic(){System.out.println("我是person类中的静态方法");}
}

主方法:

package test;public class Test {public static void main(String[] args){//加载类的过程---静态元素已经加载new Person();//p.hashCode();//1.加载父类//2.父类会产生自己的静态空间   属性 方法 块//      执行静态块//3.加载子类//4.子类会产生自己的静态空间   属性 方法 块//      执行静态块//--------------------------------------------------//5.开辟对象空间//6.加载父类的非静态成员   属性 方法 块 构造方法//7.    执行块  执行父类构造方法//8.加载子类的非静态成员   属性 方法 块 构造方法//9.    执行块  执行子类构造方法//10.将对象空间的地址引用交给 变量来存储   Person p = new Person();}
}

在这里插入图片描述

先加载父类Animal模板,加载父类模板同时就加载了Animal静态元素空间。
然后加载子类Person,顺道直接加载了子类Person类的静态元素空间。
静态元素空间存放的是静态的属性,方法和块。
运行new Person()的过程:
加载类的过程-----静态元素已经加载
先1.加载父类
2.父类会产生自己的静态空间 静态的属性 方法 块 执行块
执行静态块
3.加载子类
4.子类会产生自己的静态空间 静态的属性 方法 块 执行块
执行静态块
然后执行new Person()
5.开辟对象空间
6.加载父类的非静态成员 属性 方法 块 构造方法
7.执行块 执行父类构造方法
8.加载子类的非静态成员 属性 方法 块 构造方法
9.执行块 执行子类构造方法
10.将对象空间的地址引用交给 变量来存储


输出结果以及分析:
先1.加载父类
2.父类会产生自己的静态空间 静态的属性 方法 块 执行块
执行静态块
Aniaml静态块中调用了静态方法Animal.testStatic();,所以先执行了静态方法,输出我是animal类中的静态方法,这也说明了:静态方法已经加载好了,在创建对象之前就加载好了,所以即使没有创建对象也可以调用。同时也说明静态方法是需要调用才会执行的,不是加载类就执行。除了构造函数以外的任何方法,都需要调用才可以执行。
然后继续执行静态块中的第二句:System.out.println("我是animal中的静态代码块"+testStatic);输出:我是animal中的静态代码块AnimalStaticField


3.加载子类
4.子类会产生自己的静态空间 静态的属性 方法 块 执行块
执行静态块
Person类中的静态块,也是先调用了静态方法 Person.testStatic();,所以先输出我是person类中的静态方法。然后继续执行静态块中的第二句:System.out.println("我是person中的静态代码块"+testStatic);输出:我是person中的静态代码块personStaticField


然后执行new Person()
通过new,先5.开辟对象空间
6.加载父类的非静态成员 属性 方法 块 构造方法
7.执行块 执行父类构造方法 。先执行块,this.test(); //块中调用了普通方法,输出:我是animal类中的普通方法。然后执行块中的第二句:System.out.println("我是animal中的普通代码块"+test);输出我是animal中的普通代码块AnimalField。执行父类的构造方法:System.out.println("我是animal中默认无参数的构造方法");输出:我是animal中默认无参数的构造方法

8.加载子类的非静态成员 属性 方法 块 构造方法
9.执行块 执行子类构造方法。 先执行块,块中调用了普通方法:this.testPerson(); //调用了普通方法,所以输出:我是person类中的普通方法。然后执行块中的第二句,输出我是person中的普通代码块personField。最后执行构造方法,输出:我是person中默认无参数的构造方法

实际上默认执行的东西只有块和构造函数,其他的方法都必须被调用才能执行。还有一点指的注意的就是:静态的变量是在加载类的同时加载的,但是只是加载,并不会自动运行方法,只会自动运行块。

六、native

  • Java源代码中看到native就已经再也看不见后续代码
  • 后续会调用其他的编程语言C++ , C执行内存的操作 , 帮我们操作内存。
  • Object类中一个方法:hashCode

七、abstract

abstract:抽象的—(很不具体 没有具体的执行 只是个概念)
例子:
基类:基类中的方法,只有一个结构,没有方法执行体。

package abstracttt;public abstract class Animal {//抽象方法public abstract void eat();//残次品
}
  1. 可以修饰什么
  • 修饰方法
  • 用abstract修饰符修饰的方法 只有方法的结构 没有方法执行体叫做抽象方法
  • 当然注意native修饰的方法虽然也没有方法体 但是不是抽象方法 只是执行的过程是其他语言写的 看不见
  • 修饰类
  • 用abstract修饰符修饰的类 叫做抽象类
  1. 修饰后有什么特点
  • 抽象类中必须有抽象方法么? 不是必须含有抽象方法
  • 抽象方法必须放在抽象类中么? 目前来看必须放在抽象类中(或接口中) 普通类是不允许含有抽象方法。
  1. 研究一下什么叫抽象类 ,抽象类有什么特点?(通常用来描述事物 还不是很具体)。
    刚才的Animal就是一个抽象类。
  • 类里面有什么 成员
    (1)属性:可以含有一般的属性 ,也可以含有 private static final等等
    (2)方法:可以含有一般的方法 ,也可以含有 private static final等等
    注意:抽象类中是允许含有抽象方法(只有方法结构,没有方法执行体)
    (3):可以含有一般的程序块 也可以含有static程序块
    (4)构造方法:可以含有构造方法, 包括重载,但是我们不能通过调用构造方法直接创建对象
  • 类如何使用 创建对象
    (1) 抽象类含有构造方法,但是我们不能通过调用构造方法直接创建对象
    (2)抽象类只能通过子类单继承来做事
    为什么不让我们调用构造方法创建对象?为什么还有呢?
  • 类和类的关系
    抽象类----直接单继承----抽象类 可以
    抽象类----直接单继承----具体类 可以 (用法通常不会出现)
    具体类----直接单继承----抽象类 不可以直接继承 (将父类的抽象方法具体化 或子类也变成抽象类)
  • 小问题
    (1)抽象类中能不能没有抽象方法,全部都是具体成员-----可以
    (2)抽象类中能不能没有具体成员,全部都是抽象方法----- 可以 —> 抽象类抽象到极致 质的变化 —> 接口
    (3)接口可以理解为是抽象类抽象到极致—>还是一个类的结构 不能用class修饰 改用interface修饰

八、接口

什么是接口(通常是为了定义规则)

  • 接口也是一个类的结构 只不过 用interface修饰 替换原有的class
  1. 有什么 成员
    属性: 不能含有一般属性,只能含有 公有的静态的常量 public static final
    方法: 不能含有一般方法,只能含有 公有的抽象的方法(1.8 defualt修饰具体方法)
    : 不能含有一般程序块,也不能含有static块(块本身就是具体的,接口中不让有具体的)
    构造方法:不能含有构造方法
  2. 如何使用 创建对象
    不能创建对象
    只能通过子类多实现(implements)来做事
public class A implements B,C,D{}
  1. 与别的类结构关系
    接口不能继承别的类 最抽象
    抽象类----直接多实现----接口 可以
    具体类----直接多实现----接口 不可以直接 (必须将接口中的抽象方法具体化 或者 自己变成抽象类)
    *接口—多继承—接口 可以直接多实现

在这里插入图片描述

接口的子类必须实现接口中全部的方法吗?答案:不是。原因如下:

如果子类是非抽象类,则必须实现接口中的所有方法;
如果子类是抽象类,则可以不实现接口中的所有方法,因为抽象类中允许有抽象方法的存在!

这篇关于java学习基础课之面向对象(渡一教育)【修饰符】(六)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/501760

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06