面向对象-父类、子类、静态代码初始化顺序!

初始化顺序

类初始化顺序

代码

public class Parent {
    public int parentNum=0;
    public static int staticParentNum=0;
    
    {
        System.out.println("Parent---执行非静态代码块了1!");
    }
    
    {
        System.out.println("Parent---执行非静态代码块了2!");
    }
    
    static{
        System.out.println("Parent---执行静态代码块了1!");
    }
    
    static{
        System.out.println("Parent---执行静态代码块了2!");
    }

    public Parent(){
        System.out.println("Parent---无参构造函数!");
    }
    public Parent(int parentNum){
        this.parentNum=parentNum;
        System.out.println("Parent---有参构造函数!");
        
    }

    public void ParentMethod(int parentNum){
        this.parentNum=parentNum;
        System.out.println("Parent---非静态方法/parentNum="+parentNum);
    }
    
    public static void staticParentMethod(int staticParentNum){
        Parent.staticParentNum=staticParentNum;
        System.out.println("Parent---静态方法/staticParentNum="+staticParentNum);
    }
    
}
public class Child extends Parent{

    public int childNum=0;
    public static int staticChildNum=0;
    
    {
        System.out.println("Child---执行非静态代码块了1!");
    }
    
    {
        System.out.println("Child---执行非静态代码块了2!");
    }
    
    static{
        System.out.println("Child---执行静态代码块了1!");
    }
    
    static{
        System.out.println("Child---执行静态代码块了2!");
    }

    public Child(){
        super();
        System.out.println("Child---无参构造函数!");
    }
    
    public Child(int childNum){
        super(childNum);
        System.out.println("Child---有参构造函数!");
    }
    
    public void childMethod(int childNum){
        this.childNum=childNum;
        System.out.println("Child--非静态方法/childNum="+childNum);
    }
    
    public static void staticChildMethod(int staticChildNum){
        Child.staticChildNum=staticChildNum;
        System.out.println("Child---静态方法/staticChildNum="+staticChildNum);
    }

    
}
package test;

public class Test {

//    static{
//        System.out.println("Test---静态代码块!");
//    }
    public static void main(String[] args) {
        int key=10;
        switch (key) {
        case 0:
            Parent parent=new Parent();
            break;
//            Parent---执行静态代码块了1!
//            Parent---执行静态代码块了2!
//            Parent---执行非静态代码块了1!
//            Parent---执行非静态代码块了2!
//            Parent---无参构造函数!
//          说明:先加载静态代码块,后加载非静态代码块
        case 1:
            Child b= new Child();
            break;
//            Parent---执行静态代码块了1!
//            Parent---执行静态代码块了2!
//            Child---执行静态代码块了1!
//            Child---执行静态代码块了2!
//            Parent---执行非静态代码块了1!
//            Parent---执行非静态代码块了2!
//            Parent---无参构造函数!
//            Child---执行非静态代码块了1!
//            Child---执行非静态代码块了2!
//            Child---无参构造函数!
//            说明:创建子类,会先执行父类,先执行父类静态——>子类静态——>父类非静态——>父类构造
//——>子类非静态——>子类构造
        case 2:
            Child c= new Child(4);
            //这个构造函数中指明了调用父类的有参构造函数,若不指定,则调用父类无参构造函数
            break;
//            Parent---执行静态代码块了1!
//            Parent---执行静态代码块了2!
//            Child---执行静态代码块了1!
//            Child---执行静态代码块了2!
//            Parent---执行非静态代码块了1!
//            Parent---执行非静态代码块了2!
//            Parent---有参构造函数!
//            Child---执行非静态代码块了1!
//            Child---执行非静态代码块了2!
//            Child---有参构造函数!
            说明:静态代码块或非静态代码块执行顺序,按照代码前后编写顺序。
        case 3:
            Child d= new Child();
            Child e= new Child(4);
            break;
//            Parent---执行静态代码块了1!
//            Parent---执行静态代码块了2!
//            Child---执行静态代码块了1!
//            Child---执行静态代码块了2!
//            Parent---执行非静态代码块了1!
//            Parent---执行非静态代码块了2!
//            Parent---无参构造函数!
//            Child---执行非静态代码块了1!
//            Child---执行非静态代码块了2!
//            Child---无参构造函数!
//            Parent---执行非静态代码块了1!
//            Parent---执行非静态代码块了2!
//            Parent---有参构造函数!
//            Child---执行非静态代码块了1!
//            Child---执行非静态代码块了2!
//            Child---有参构造函数!
            说明:创建多个子类,但父类静态代码块只执行一次。
        case 4:
            Child.staticChildMethod(4);
            break;
//            Parent---执行静态代码块了1!
//            Parent---执行静态代码块了2!
//            Child---执行静态代码块了1!
//            Child---执行静态代码块了2!
//            Child---静态方法/staticChildNum=4
            说明:静态方法只可以调用静态变量。
        case 5:
            Parent.staticParentMethod(5);
            break;
//            Parent---执行静态代码块了1!
//            Parent---执行静态代码块了2!
//            Parent---静态方法/staticParentNum=5
            说明:静态方法可通过 父类名.静态方法() 调用。
        case 6:
            System.out.println("父类的静态变量值staticParentNum="+Parent.staticParentNum);
            break;
//            Parent---执行静态代码块了1!
//            Parent---执行静态代码块了2!
//            父类的静态变量值staticParentNum=0
            说明:调用静态变量时,静态代码块会执行。
        case 7:
            System.out.println("子类的静态变量值staticChildNum="+Child.staticChildNum);
            break;
//            Parent---执行静态代码块了1!
//            Parent---执行静态代码块了2!
//            Child---执行静态代码块了1!
//            Child---执行静态代码块了2!
//            子类的静态变量值staticChildNum=0
            说明:调用子类静态变量,父类静态代码块和子类静态代码块会被执行。
        case 8:
            System.out.println("父类的静态变量值staticParentNum="+Parent.staticParentNum);
            System.out.println("子类的静态变量值staticChildNum="+Child.staticChildNum);
            break;
//            Parent---执行静态代码块了1!
//            Parent---执行静态代码块了2!
//            父类的静态变量值staticParentNum=0
//            Child---执行静态代码块了1!
//            Child---执行静态代码块了2!
//            子类的静态变量值staticChildNum=0
            说明:先调用父类,后调用子类静态变量,父类静态代码块只被执行一次。
        case 9:
            Child f= new Child();
            f.ParentMethod(3);
            break;
//            Parent---执行静态代码块了1!
//            Parent---执行静态代码块了2!
//            Child---执行静态代码块了1!
//            Child---执行静态代码块了2!
//            Parent---执行非静态代码块了1!
//            Parent---执行非静态代码块了2!
//            Parent---无参构造函数!
//            Child---执行非静态代码块了1!
//            Child---执行非静态代码块了2!
//            Child---无参构造函数!
//            Parent---非静态方法/parentNum=3
            说明:创建子类,用子类调用父类方法,非静态方法可以调用静态变量。

        default:
            break;
        }
    }
}

结论

  1. 实例化一个对象:先加载静态代码块,后加载非静态代码块
  2. 实例化子类对象:父类静态——>子类静态——>父类非静态——>父类构造——>子类非静态——>子类构造;
  3. 实例化多个子类对象:父类静态代码块只执行一次,非静态和构造都执行多次;
  4. 调用子类静态变量:父类静态代码块->子类静态代码块->静态变量
  5. 实例化子类对象
### 1. CSRF漏洞原理 CSRF(跨站请求伪造)是一种欺骗性的攻击方式,其核心在于让受害者在不知情的情况下执行某些操作。这种攻击通常发生在用户已经登录某个网站并保持会话状态时。攻击者通过诱导用户访问恶意页面,在该页面上嵌入指向目标网站的操作链接或表单提交脚本。由于浏览器会在发送请求时自动附带当前用户的认证信息(如Cookie),从而使得这些请求被当作合法请求处理。 例如,假设某银行网站允许用户转账的接口如下: ```http POST /transfer HTTP/1.1 Host: bank.example.com Content-Type: application/x-www-form-urlencoded to=attacker_account&amount=1000 ``` 如果用户已登录此银行网站且未退出,则攻击者可以通过构造类似的HTML代码诱使用户触发转账行为: ```html <img src="https://bank.example.com/transfer?to=attacker_account&amount=1000"> ``` 当受害者的浏览器加载上述`<img>`标签时,实际上向银行发起了一个GET请求,并携带了用户的Session Cookie[^1]。 --- ### 2. SSRF漏洞原理 SSRF(服务器端请求伪造)是指攻击者能够操控服务器去发起对外部或者内部网络资源的HTTP请求。这类漏洞通常是因程序设计缺陷引起——即开发者未能充分验证来自客户端输入的数据便将其用于构建远程调用逻辑。比如文件上传功能可能接受外部URL作为参数下载图片到本地存储;又或者是缓存预热机制定期抓取指定网页内容等等场景都可能存在风险点。 具体来说,假如存在这样一个API用来获取第三方数据: ```python @app.route('/fetch') def fetch(): url = request.args.get('url') # 用户可控制变量 response = requests.get(url) # 使用未经校验的 URL 发起 GET 请求 return response.content # 返回响应体给前端展示 ``` 此时,若无任何防护措施的话,那么攻击者就可以轻易地传入任意地址,包括但不限于私有子网范围内的IP地址或者其他敏感服务的位置,进而实现对内网资产扫描探测甚至进一步渗透的目的[^4]。 --- ### 3. 区别与联系 #### **主要区别** - **发起方不同**: - CSRF 是由 客户端 (User Agent, 如 Web 浏览器卡) 所发出的请求; - 而 SSRF 则完全是在 后台 Server 层面产生的动作。 - **影响对象差异**: - 对于前者而言主要是针对那些依赖 Cookies 或其他形式的身份标识来进行身份确认的服务造成威胁; - 至于后者更多时候涉及到的是对企业内部架构安全性的挑战,因为它可以让黑客突破防火墙限制接触到原本隔离起来的重要设施服务实例[^3]. - **技术层面特点对比**: - 在 CSRF 中,整个过程都需要借助真实用户的交互才能顺利完成(点击链接、浏览特定网页等),而且最终所形成的危害程度取决于目标站点赋予该名下的实际权限大小; - 反观 SSRF ,一旦成功利用之后即可直接绕过常规意义上的边界保护策略,无论是否有正常用户的参与均能达成预期效果. #### **共同之处** 尽管两者之间存在着诸多显著的不同特征,但也共享了一些相似属性: - 都属于典型的Web应用层面上存在的安全隐患类别之一; - 成功实施的前提条件都是要找到合适的入口点以及具备一定的可控因素可供操纵调整 ; - 解决方案方面也都强调采用多层次综合手段相结合的方式来提升整体系统的安全性水平 , 比如说引入验证码机制对抗自动化工具生成虚假流量现象; 加强输入过滤规则防止非法字符混入业务流程当中等等举措都可以有效降低遭受此类攻击的概率 。 --- ### 示例代码片段 以下是两种常见防御方法的一个简单例子: 对于CSRF,可以在每次表单提交前加入动态Token验证: ```javascript // 前端部分 function csrfSafeMethod(method) { var token = $("meta[name='_csrf']").attr("content"); return /^(GET|HEAD|OPTIONS|TRACE)$/.test(method) || !!token && arguments.length === 2 ? { _csrf_token : token } : {}; } $.ajax({ type: 'POST', data: $.extend(csrfSafeMethod(), { key: value }), ... }); ``` 而后端需同步检查这个额外传递过来的信息是否匹配预先设定好的值[^2]: ```php <?php if ($_SERVER['REQUEST_METHOD'] === 'POST') { $expectedToken = $_SESSION['_csrf_token']; if (!hash_equals($expectedToken, $_POST['_csrf_token'])) { die('Invalid CSRF Token!'); } } ?> ``` 至于SSRF,最基础的做法就是限定允许访问的目标域名列表: ```python import urllib.parse ALLOWED_HOSTS = ['example.com', 'api.example.org'] @app.route('/proxy') def proxy(): target_url = request.args.get('url') parsed_url = urllib.parse.urlparse(target_url) if parsed_url.netloc not in ALLOWED_HOSTS: abort(403) # Forbidden access resp = requests.get(target_url) return Response(resp.content, content_type=resp.headers['content-type']) ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值