当前位置: 首页 > news >正文

JS 原型与继承

   本文内容学习于:后盾人 (houdunren.com)

一、原型对象
每个对象都有一个原型prototype对象,通过函数创建的对象也将拥有这个原型对象。

原型是一个指向对象的指针。

1.可以将原型理解为对象的父亲,对象从原型对象继承来属性

2.原型就是对象除了是某个对象的父母外没有什么特别之处
3.所有函数的原型默认是 Object的实例,所以可以使用toString/toValues/isPrototypeof 等方法的原因

4.使用原型对象为多个对象共享属性或方法
5.如果对象本身不存在属性或方法将到原型上查找
6.使用原型可以解决,通过构建函数创建对象时复制多个函数造成的内存占用问题

7.原型包含 constructor 属性,指向构造函数

8.对象包含proto指向他的原型对象


1.关于创建原型
Object.getPrototypeof() //返回指定对象的原型
Object.create()// 创建一个新对象,使用现有的对象来作为新创建对象的原型

// 创建一个xj对象,但是它的原型指定为Null,

let xj = Object.create(null, { name:{value:"向军"});
console.log(xj.hasOwnProperty("name"));

//Error hasOwnProperty是object原型上的方法,null上面没有


2.函数拥有多个原型,prototype 用于实例对象使用, __proto__用于函数对象使用


3.使用 setPrototypeof 与 getPrototypeof 获取与设置原型

Object.setPrototypeOf(obj, prototype)//obj 要设置其原型的对象 ,prototype 该对象的新原型(一个对象或 null)。

Object.getPrototypeof(object)// 要返回其原型的对象。

二、原型检测

instanceof 检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

isPrototypeof 检测一个对象是否是另一个对象的原型链中


三、属性遍历
1.使用in 检测原型链上是否存在属性,使用 hasOwnProperty 只检测当前对象

let a = { url: "houdunren" };

let b = { name:"后盾人"};

Object.setPrototypeof(a, b);

console.log("name" in a);
console.log(a.hasOwnProperty("name"));

console.log(a.hasOwnProperty("url"));


2.使用 for/in 遍历时同时会遍历原型上的属性

let hd = { name:"后盾人"};

let xj = Object.create(hd, { url:{value: "houdunren.com", enumerable: true});
for (const key in xj) {
        console.log(key);

}

3.hasOwnProperty 方法判断对象是否存在属性,而不会查找原型。

所以如果只想遍历对象属性使用以下代码

let hd = { name:"后盾人"}; let xj = Object.create(hd, {
url:{
value: "houdunren.com", enumerable: true
}
});
for (const key in xj) {
if (xj.hasOwnProperty(key)){
console.log(key);}

ps:this 不受原型继承影响,this 指向调用属性时使用的对象。

四、原型总结

<1>. prototype
函数也是对象也有原型,函数有 prototype 属性指向他的原型
为构造函数设置的原型指,当使用构造函数创建对象时把这个原型赋予给这个对象

1.函数默认prototype 指包含一个属性 constructor 的对象,constructor 指向当前构造函数

function User(name) {
this.name = name;
let xj = new User("向军"); console.log(xj);
console.log(User.prototype.constructor == User); //true console.log(xj. proto == User.prototype);//true
let lisi = new xi.constructor("李四");
console.log(lisi._proto__== xj._proto__); //true

<2>. Object.create
使用object.create创建一个新对象时使用现有对象做为新对象的原型对象


1.使用object.create 设置对象原型

let user = { show() {
return this.name;

};
let hd = Object.create(user); hd.name ="向军";
console.log(hd.show(());


2.在设置时使用第二个参数设置新对象的属性

let user = { show() {
return this.name;

};
let hd = Object.create(user, {
name:{
value:"后盾人"}
});
console.log(hd);


<3>.__proto__
在实例化对象上存在 __proto__记录了原型,所以可以通过对象访问到原型的属性或方法。

1.__proto__不是对象属性,理解为prototype 的 getter/setter 实现,他是一个非标准定义

2.__proto__内部使用getter/setter 控制值,所以只允许对象或 null
3.建议使用 Object.setPrototypeOf 与Object.getProttoeypof 替代 proto

特例:下面定义的_proto就会成功,因为这是一个极简对象,没有原型对象所以不会影响_proto赋值。

let hd = Object.create(null);

hd._proto__= "向军";
console.log(hd);//{__proto_:"向军"}


1.可以通过改变对象的 proto 原型对象来实现继承,继承可以实现多层,

let hd = {name:"后盾人"};
let houdunren = {show() {return this.name;}};
let xj = { handle() {return '用户:${this.name}`;}};
houdunren. proto =xj;

hd. proto = houdunren;

console.log(hd.show());

console.log(hd.handle(());

console.log(hd);


2.可以使用 proto 或 Object.setPrototypeof 设置对象的原型,使用object.getProttoeypof 获取对象原型

function Person() {
this.getName = function() {
return this.name;};
function User(name, age){
this.name = name; this.age = age;
let lisi = new User("李四",12);
Object.setPrototypeof(lisi, new Person()); console.log(lisi.getName());//李四

3.对象设置属性,只是修改对象属性并不会修改原型属性,使用hasOwnProperty 判断对象本身是否含有属性,并不会检测原型。


4.使用 in 会检测原型与对象,而 hasOwnProperty 只检测对象,所以结合后可判断属性是否在原型中

function User() {
User.prototype.name = "后盾人"; const lisi = new User();//in会在原型中检测
console.log("name" in lisi);//true 对象的原型上有//hasOwnProperty 检测对象属性
console.log(lisi.hasOwnProperty("name"));//false 对象本身上没有


五、原型使用建议总结:
1.prototype 构造函数的原型属性
2.Object.create 创建对象时指定原型
3.proto 声明自定义的非标准属性设置原型,解决之前通过 Object.create 定义原型,而没提供获取方法
4.Object.setPrototypeof 设置对象原型
这几种方式都可以管理原型,一般以我个人情况来讲使用prototype更改构造函数原型,使用Ob1ect.setPrototypeof与 obiect.getPrototypeof获取或设置原型


六、构造函数:
1.原型属性
1)构造函数在被new时把构造函数的原型(prototype)赋值给新对象。如果对象中存在属性将使用对象属性,不再原型上查找方法。


2)对象的原型引用构造函数的原型对象,是在创建对象时确定的,当构造函数原型对象改变时会影响后面的实例对象。之前已经创建的实例对象不受影响

function hd() {}
hd.prototype.name = "hdcms"; const objl = new hd();
console.log(objl.name); //hdcms
hd.prototype ={ name:"后盾人"};
const obj2 = new hd(();
console.dir(obj2.name);//后盾人
console.log(obj1.name);//hdcms //还是原来的,不受影响

2.constructor
1)构造函数的原型中包含属性 constructor 指向该构造函数

function User(name) {this.name = name;}

let hd = new User("后盾人");
let xj = new hd.constructor("向军"); console.log(xj);


2)直接设置了构造函数的原型将造成 constructor丢失!!!正确的做法是要保证原型中的constructor指向构造函数

function User(name) {this.name = name;}
User.prototype = {constructor: User,// 保证constructor指向构造函数 show:function() {}};
let hd = new User("后盾人");
let xj = new hd.constructor("向军"); console.log(xj);


3.使用优化
注意:使用构造函数会产生函数复制造成内存占用,及函数不能共享的问题。

function User(name) {
this.name = name;
this.get = function() {
return this.name;};
let lisi = new User("小明"); let wangwu = new User("王五");
console.log(lisi.get == wangwu.get); //false

正确方式;通过原型定义方法不会产生函数复制,所有对象公用构造函数原型上方法(解决、通过构造函数创建对象函数复制”的内存占用问题!)

function User(name) {
this.name =name;

User.prototype.get = function() { return "后盾人"+this.name;};
let lisi = new User("小明");
let wangwu = new User("王五");
console.log(lisi.get == wangwu.get); //true
//通过修改原型方法会影响所有对象调用,因为方法是共用的 lisi. proto .get= function() { return "后盾人"+this.name;
console.log(lisi.get());

console.log(wangwu.get());

七、继承与多态
当对象中没使用的属性时,Js 会从原型上获取这就是继承在 JavaScript 中的实现。


1.继承实现
使用object.create 创建对象,做为Admin、Member的原型对象来实现继承。

function User() {}
User.prototype.getUserName = function() {};


function Admin(() {}
Admin.prototype = Object.create(User.prototype);

Admin.prototype.role = function() {};

function Member() {}
Member.prototype = Object.create(User.prototype);

Member.prototype.email = function() {}; console.log(new Admin(());

console.log(new Member ());

注意:不能使用以下方式操作,因为这样会改变 User 的原型方法,这不是继承,这是改变原型!!!

function User() {}
User.prototype.getUserName = function(() {};


function Admin(() {}
Admin.prototype=User.prototype;
Admin.prototype.role = function(() {};


2.构造函数
1)有多种方式通过构造函数创建对象

function Admin() {}
console.log(Admin == Admin.prototype.constructor); //true
let hd =new Admin.prototype.constructor();

console.log(hd);
let xj = new Admin ();

console.log(xj);


2)因为有时根据得到的对象获取构造函数,然后再创建新对象所以需要保证构造函数存在,
但如果直接设置了 Admin.prototype 属性会造成constructor丢失,所以需要再次设置constructor值。

function User() {}

function Admin() {}


Admin.prototype =Object.create(User.prototype);

Admin.prototype.role= function(){};


let xj = new Admin ();
console.log(xj.constructor);//constructor丢失,返回User构造函数


Admin.prototype.constructor = Admin;

let hd = new Admin ();
console.log(hd.constructor);//正确返回Admin构造函数
//现在可以通过对象获取构造函数来创建新对象了 console.log(new hd.constructor());


3)使用object.defineProperty定义来禁止遍历 constructor属性

function User() {}
function Admin(name) {this.name = name;}
Admin.prototype =Object.create(User.prototype);

Object.defineProperty(Admin.prototype, "constructor",

{value: Admin,enumerable: false //禁止遍历});
let hd = new Admin("后盾人"); for (const key in hd) {
console.log(key);}

注意:完全重写构建函数原型,只对后面应用对象有效!

3.方法重写

//子类需要重写父类方法的技巧。

function Person() {}
Person.prototype.getName= function() {console.log("parent method");};

function User(name) {}
User.prototype=Object.create(Person.prototype);

User.prototype.constructor=User;
User.prototype.getName= function(() {//调用父级同名方法Person.prototype.getName.call(this); console.log("child method");};
let hd = new User(); hd.getName();

4.多态
根据多种不同的形态产生不同的结果,下而会"根据不同形态的对象得到了不同的结果”。

function User() {}
User.prototype.show=function() {
console.log(this.description());};
function Admin() {}
Admin.prototype =Object.create(User.prototype); Admin.prototype.description = function() { return "管理员在此";};
function Member() {}
Member.prototype =Object.create(User.prototype); Member.prototype.description = function() { return "我是会员";};
function Enterprise() {}
Enterprise.prototype =Object.create(User.prototype); Enterprise.prototype.description = function() { return "企业帐户";

for (const obj of[new Admin(), new Member(), new Enterprise()]) {
obj.show();}


八、深挖继承
继承是为了复用代码,继承的本质是将原型指向到另一个对象。


1.构造函数
我们希望调用父类构造函数完成对象的属性初始化,但像下面这样使用是不会成功的。因为此时 this 指向了 window,无法为当前对象声明属性。

function User(name) {
this.name = name;
console.log(this);// Window

User.prototype.getUserName=function() {
return this.name;
);
function Admin(name) { User(name);

Admin.prototype=Object.create(User.prototype); Admin.prototype.role= function() {};
let xj = new Admin("向军大叔");
console.log(xj.getUserName());//undefined


解决上面的问题是使用 cal1/apply 为每个生成的对象设置属性

function User(name) {
this.name = name;
console.log(this); // Admin

User.prototype.getUserName=function(() {
return this.name;};

function Admin(name) {
User.call(this, name);
Admin.prototype =Object.create(User.prototype);
let xj = new Admin("向军大叔");
console.log(xj.getUserName());//向军大叔

2.函数的 apply()与call()
ps:call的第一个参数,就是改变函数的作用域,后面的参数为传入函数的所需的参数,必须与原函数的参数一直

<script type="text/javascript">
var testo = { name: "Lily" }; function funcA(a,b) {
alert(this);
alert("Function A");

function funcB(a,b) {
funcA.call(testo, a,b);

funcB(1,2); //this变成了testo

</script>


我们定义funcB函数的中,调用了funca的call函数,这个时候我们改变了funca中this的指向,原本指向window的,现在指向了cal1的第一个参数testo这个对象。而目调用call时,因为funca函数有两个参数,所以如果要想funca传递参数,必须--指出参数,即后面的两个参数a和n,或者可以只传第一个参数

即:funcA.call(testo);或者只传a,即:funcA.call(testo,a);


而apply与cal1的区别仅在于,apply的第二个参数可以是数组形式,而且不必--指出参数,funcA.apply(testo,[a,b])

3.原型工厂
原型工厂是将继承的过程封装,使用继承业务简单化

function extend(sub, sup){
sub.prototype=Object.create(sup.prototype);

sub.prototype.constructor = sub;

}

function Access() {}

function User(() {}

function Admin() {}

function Member() {}
extend(User,Access);//User继Access

extend(Admin,User);//Admin继承User
extend(Member,Access);//Member继承Access
Access.prototype.rules = function(() {};

User.prototype.getName= function(){};
console.log(new Admin());// 继承关系:Admin>User>Access>Object

console.log(new Member());//继本关系:Member>Access>Object


4.对象工厂
在原型继承基础上,将对象的生成使用函数完成,并在函数内部为对象添加属性或方法。

function User(name, age) {
this.name = name; this.age = age;
User.prototype.show= function () {
console.log(this.name, this.age);};

function Admin(name,age){
let instance =Object.create(User.prototype); User.call(instance, name, age); instance.role=function(){
console.log('admin.role');}
return instance;

let hd = Admin("后盾人",19); hd.show();
function member(name, age) {
let instance = Object.create(User.prototype); User.call(instance, name, age); return instance;

let lisi = member("李四",28); lisi.show();

相关文章:

JS 原型与继承

本文内容学习于&#xff1a;后盾人 (houdunren.com) 一、原型对象 每个对象都有一个原型prototype对象&#xff0c;通过函数创建的对象也将拥有这个原型对象。 原型是一个指向对象的指针。 1.可以将原型理解为对象的父亲&#xff0c;对象从原型对象继承来属性 2.原型就是对象…...

解决 Oracle 数据库中表被锁问题的方案和方法

我们经常会遇到表被锁的情况&#xff0c;这可能会严重影响数据库的性能和可用性。我将与大家分享如何识别、分析和解决这些问题&#xff0c;以及如何使用特定的 SQL 查询来执行解锁操作。 了解表锁的原因 首先&#xff0c;让我们来了解一下导致表被锁的常见原因。长时间运行的…...

ORACLE行转列、列转行实现方式及案例

ORACLE行转列、列转行实现方式及案例 行转列案例方式1.PIVOT方式2.MAX和DECODE方式3.CASE WHEN和GROUP BY 列转行案例方式1.UNPIVOT方式2.UNION ALL 行转列 案例 假设我们有一个名为sales的表&#xff0c;其中包含了产品销售数据。表中有三列&#xff1a;product&#xff08;…...

AI自动驾驶

AI自动驾驶 一、自动驾驶的原理二、自动驾驶的分类三、自动驾驶的挑战四、自动驾驶的前景五、关键技术六、自动驾驶的安全问题七、AI数据与自动驾驶八、自动驾驶的AI算法总结 自动驾驶技术是近年来备受关注的热门话题。它代表了人工智能和机器学习在汽车行业的重要应用。本文将…...

思维导图在职业规划中的应用:从职业选择到职业发展的思维导图

职业规划的重要性 在我们进行职业选择的时候&#xff0c;一个有效的职业规划&#xff0c;会对我们的未来有很大的帮助作用。一个好的职业规划可以帮助我们通过认识自己的兴趣、价值观、技能以及优势&#xff0c;找到适合自己的领域。并做出合理有效的职业选择。有了明确的职业目…...

antv l7每次刷新无法加载iconFont

如图&#xff0c;只渲染出了文本&#xff0c;未渲染出iconFont 但是如果我跳转到其他页面再跳转回来(未经过刷新时)&#xff0c;可以展示出iconFont 解决&#xff1a; 查看官方源码后 找到了iconfont.tsx文件 可以看到多了一步font loaded&#xff0c; 放到项目中后再次测试&…...

28 玻尔兹曼机

文章目录 28 玻尔兹曼机28.1 模型定义28.2 梯度推导28.3 梯度上升28.4 基于VI[平均场理论]求解后验概率 28 玻尔兹曼机 28.1 模型定义 玻尔兹曼机是一张无向图&#xff0c;其中的隐节点和观测节点可以有任意连接如下图&#xff1a; 我们给其中的节点、连线做出一些定义&#…...

命令提示符之操作基础(Windows)

打开命令提示符 方法一 打开指定文件的文件夹&#xff0c;在路径栏里输入“cmd”&#xff0c;回车&#xff0c;就进入控制台了。默认路径就是指定文件夹的路径。 方法二 打开指定的文件夹&#xff0c;按住shift键&#xff0c;在空白处右击&#xff0c;在菜单栏中选择“在此处打…...

【C语言】初识C语言+进阶篇导读

✨个人主页&#xff1a; Anmia.&#x1f389;所属专栏&#xff1a; C Language &#x1f383;操作环境&#xff1a; Visual Studio 2019 版本 本篇目的是面向编程新手&#xff0c;没接触过编程的人。以及C进阶的导读。 内容是C语言重要知识点的简单解释&#xff0c;不做详解。给…...

wxWidgets学习笔记:wxListCtrl使用详解

使用案例 wxListCtrl中放21个item&#xff0c;每一行放两个item&#xff0c;每个item显示图标和名字&#xff0c;点击某个图标&#xff0c;该图标呈现响应状态并响应对应的事件 以下是使用wxListCtrl实现放置21个item&#xff0c;每一行放两个item&#xff0c;每个item显示图…...

酷炫的python日志库-loguru

Loguru是一个python的日志库&#xff0c;比logging更简单&#xff0c;好用&#xff0c;功能丰富。 GitHub - Delgan/loguru: Python logging made (stupidly) simple 安装 pip install loguru 特征 开箱即用&#xff0c;补样板没有处理程序&#xff0c;没有清理程序&#xff…...

html根据图片变换背景色

html根据图片变换背景色 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style>.item {width: 50%;height: 80vh;margin: 0 auto;border: 1px solid red;}</style> </head><body>…...

“深入探究JVM:揭秘Java虚拟机的工作原理“

标题&#xff1a;深入探究JVM&#xff1a;揭秘Java虚拟机的工作原理 摘要&#xff1a;本文将深入探究Java虚拟机&#xff08;JVM&#xff09;的工作原理&#xff0c;包括JVM的架构、内存管理、垃圾回收机制以及即时编译等关键概念。通过详细解释这些概念&#xff0c;读者将能够…...

小程序的api使用 以及一些weui组件实列获取头像 扫码等

今日目标 响应式单位rpx小程序的生命周期 【重点】20%小程序框架 weui 【重点】 50%内置API 【重点】30%综合练习 1. 响应式rpx 1.1 rpx单位 rpx是微信小程序提出的一个尺寸单位&#xff0c;将整个手机屏幕宽度分为750份&#xff0c;1rpx 就是 1/750&#xff0c;避免不同手…...

海思ss928部署手写数字识别模型

大致流程--------------------------------------------------------------------------------------------------------------------- 模型转换---------------------------------------------------------------------------------------------------- 1&#xff1a;准备MNI…...

组学知识速递(五)|ChIP-seq知多少?

近段时间来&#xff0c;我们合作的ChIP-Seq技术发表的高分成功案例一篇接一篇&#xff0c;您是否心动了呢&#xff1f;本篇文章&#xff0c;总结了ChIP-Seq实验部分重点知识点&#xff0c;开启ChIP-Seq的你绝不要错过&#xff01; Q1 什么是ChIP-Seq&#xff1f; ChIP-Seq即染…...

2308C++内存序概略

参考 释放:在释放前的任意读写操作不能放在此操作之后. 获取:在获取后的任意读写操作不能放在此操作之前. 放松:只保证本操作的原子性,一般用于统计. 消费:在加载后的依赖本原子变量的,都不能重排在本操作之前. 获取释放:获取释放 序列一致,完全一致....

【C++】string的使用

1、string的使用 #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include<string> using namespace std;void Test1() {string s1;string s2("hello");cin >> s1;cout << s1 << endl;//strcat【字符串拼接】string ret1 s…...

Android 周期任务

AlarmManager使用 1.创建意图 // 创建意图&#xff0c;启动MonthlyTaskServiceIntent intent new Intent(getContext(), TimeTaskService.class); // 传递数据intent.putExtra(TimeTaskService.KEY_TITLE,userRemind.getTitle());intent.putExtra(TimeTaskService.KEY_DEC,u…...

修改第三方组件默认样式

深度选择器 修改el-input的样式&#xff1a; <el-input class"input-area"></el-input>查看DOM结构&#xff1a; 原本使用 /deep/ 但是可能不兼容 使用 :deep .input-area {:deep(.el-input__inner){background-color: blue;} }将 input 框背景色改为…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1&#xff1a;通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分&#xff0c;设置 Gradle JDK 方法2&#xff1a;通过 Settings File → Settings... (或 CtrlAltS)…...