如何设计类和接口

本文是我们名为“ 高级Java ”的学院课程的一部分。

本课程旨在帮助您最有效地使用Java。 它讨论了高级主题,包括对象创建,并发,序列化,反射等。 它将指导您完成Java掌握的过程! 在这里查看 !

目录

1.简介 2.接口 3.标记接口 4.功能接口,默认方法和静态方法 5.抽象类 6.不可变的类 7.匿名类 8.可见度 9.继承 10.多重继承 11.继承与组成 12.封装 13.期末课程和方法 14.接下来 15.下载源代码

1.简介

不管您使用哪种编程语言(这里Java也不例外),遵循良好的设计原则是编写简洁,可理解,可测试的代码并提供长期有效且易于维护的解决方案的关键因素。 在本教程的这一部分中,我们将讨论Java语言提供的基础构建块,并介绍一些设计原则,以帮助您做出更好的设计决策。

更确切地说,我们将讨论与默认的方法 接口接口 (Java 8的新功能), 抽象final 类,不可变类,继承,组成和重温了一下可见性 (或可访问)的规则,我们有部分短暂触及教程1如何创建和销毁对象

2.接口

在面向对象的编程中,接口的概念构成了契约驱动(或基于契约)开发的基础。 简而言之,接口定义方法的集合(契约),并且声称支持该特定接口的每个类都必须提供这些方法的实现:一个非常简单但功能强大的想法。

许多编程语言确实具有一种形式或另一种形式的接口,但是Java特别为此提供了语言支持。 让我们看一下Java中的简单接口定义。

package com.javacodegeeks.advanced.design;public interface SimpleInterface {void performAction();
}

在上面的代码片段中,我们命名为SimpleInterface的接口SimpleInterface声明了一个名为performAction方法。 接口相对于类的主要区别在于接口概述了联系方式(声明方法),但未提供其实现。

但是,Java中的接口可能比这更复杂:它们可以包括嵌套的接口,类,枚举,注释(该枚举和注释将在本教程的第5部分中详细介绍如何以及何时使用Enums和Annotations )和常量。 。 例如:

package com.javacodegeeks.advanced.design;public interface InterfaceWithDefinitions {String CONSTANT = "CONSTANT";enum InnerEnum {E1, E2;}class InnerClass {}interface InnerInterface {void performInnerAction();}void performAction();
}

在这个更复杂的示例中,存在一些关于嵌套构造和方法声明的接口隐式施加的约束,而Java编译器则强制执行这些约束。 首先,即使没有明确说明,该接口中的每个声明都是公共的 (并且只能是public ,有关可见性和可访问性规则的更多详细信息,请参阅Visibility部分)。 因此,以下方法声明是等效的:

public void performAction();
void performAction();

值得一提的是,接口中的每个方法都隐式声明为抽象 ,甚至这些方法声明也是等效的:

public abstract void performAction();
public void performAction();
void performAction();

至于常量字段声明,除了是public ,它们是隐式staticfinal因此以下声明也等效:

String CONSTANT = "CONSTANT";
public static final String CONSTANT = "CONSTANT";

最后,除了public之外,嵌套类,接口或枚举还隐式声明为static 。 例如,这些类声明也等效:

class InnerClass {
}static class InnerClass {
}

您将选择哪种样式是个人喜好,但是了解这些简单的界面质量可以使您避免不必要的键入。

3.标记接口

标记接口是一种特殊的接口,没有定义任何方法或其他嵌套结构。 在本教程的第2部分中 ,我们已经看到了标记接口的一个示例,该接口使用所有对象共有的方法 ,即Cloneable接口。 这是在Java库中定义的方式:

public interface Cloneable {
}

标记接口本身并不是契约,而是某种有用的技术,用于“附加”或“绑定”类的某些特定特征。 例如,对于Cloneable ,该类被标记为可用于克隆,但是它应该或可以做的方式不是接口的一部分。 标记接口的另一个非常著名且广泛使用的示例是Serializable

public interface Serializable {
}

此接口将类标记为可用于序列化和反序列化,并且再次,它未指定可以或应该完成的方式。

标记器接口虽然不能满足作为合同的接口的主要目的,但在面向对象的设计中仍占有一席之地。

4.功能接口,默认方法和静态方法

随着Java 8的发布 ,接口获得了非常有趣的新功能:静态方法,默认方法和lambda(功能性接口)的自动转换。

在接口一节中,我们强调了以下事实:Java中的接口只能声明方法,而不能提供其实现。 使用默认方法不再是事实:接口可以使用default关键字标记方法并为其提供实现。 例如:

package com.javacodegeeks.advanced.design;public interface InterfaceWithDefaultMethods {void performAction();default void performDefaulAction() {// Implementation here}
}

作为实例级别,默认方法可以被每个接口实现者覆盖,但是从现在开始,接口还可以包括static方法,例如:

package com.javacodegeeks.advanced.design;public interface InterfaceWithDefaultMethods {static void createAction() {// Implementation here}
}

可能有人说在接口中提供实现会破坏基于契约的开发的全部目的,但是将这些功能引入Java语言有很多原因,无论它们多么有用或令人困惑,它们都可以为您提供帮助采用。

功能接口是另外一个故事,并且事实证明它们是该语言的非常有用的附加组件。 基本上,功能接口是仅声明了一个抽象方法的接口。 Java标准库中的Runnable接口就是这个概念的一个很好的例子:

@FunctionalInterface
public interface Runnable {void run();
}

Java编译器以不同的方式对待功能接口,并且能够将lambda函数转换为有意义的功能接口实现。 让我们看一下以下函数定义:

public void runMe( final Runnable r ) {r.run();
}

要在Java 7及以下版本中调用此函数,应提供Runnable接口的实现(例如,使用Anonymous类 ),但是在Java 8中,使用lambda语法传递run()方法实现就足够了:

runMe( () -> System.out.println( "Run!" ) );

此外, @FunctionalInterface批注(批注将在本教程的第5部分“ 如何以及何时使用Enums和Annotations”中详细介绍 )提示编译器验证接口仅包含一种抽象方法,以便对接口中引入的任何更改未来将不会打破这一假设。

5.抽象类

Java语言支持的另一个有趣的概念是抽象类的概念。 抽象类在某种程度上类似于Java 7中的接口,并且与Java 8中具有默认方法的接口非常接近。与常规类相比,抽象类无法实例化,但可以被子类化(请参阅继承一节以获取更多详细信息)。 更重要的是,抽象类可能包含抽象方法:没有实现的特殊方法,就像接口一样。 例如:

package com.javacodegeeks.advanced.design;public abstract class SimpleAbstractClass {public void performAction() {// Implementation here}public abstract void performAnotherAction();
}

在此示例中,类SimpleAbstractClass被声明为abstract并且还具有一个abstract方法声明。 当实现细节的大部分甚至一部分可以被许多子类共享时,抽象类非常有用。 但是,它们仍然敞开了大门,并允许通过抽象方法自定义每个子类的固有行为。

值得一提的是,与只能包含public声明的接口相反,抽象类可以使用可访问性规则的全部功能来控制抽象方法的可见性(有关更多详细信息,请参见“ 可见性和继承 ”部分)。

6.不可变的类

不可变性在当今的软件开发中变得越来越重要。 多核系统的兴起引起了很多与数据共享和并发相关的担忧(在第9部分并发最佳实践中 ,我们将详细讨论那些主题)。 但是,肯定会出现一件事:可变状态的减少(甚至不存在)导致更好的可伸缩性和系统的简化推理。

不幸的是,Java语言没有为类不变性提供强大的支持。 但是,结合使用多种技术,可以设计不可变的类。 首先,该类的所有字段都应该是final 。 这是一个好的开始,但不能单独保证不变性。

package com.javacodegeeks.advanced.design;import java.util.Collection;public class ImmutableClass {private final long id;private final String[] arrayOfStrings;private final Collection< String > collectionOfString;
}

其次,遵循适当的初始化:如果字段是对集合或数组的引用,请不要直接从构造函数参数中分配这些字段,而应创建副本。 这将确保集合或数组的状态不会从外部更改。

public ImmutableClass( final long id, final String[] arrayOfStrings,final Collection< String > collectionOfString) {this.id = id;this.arrayOfStrings = Arrays.copyOf( arrayOfStrings, arrayOfStrings.length );this.collectionOfString = new ArrayList<>( collectionOfString );
}

最后,提供适当的访问器(获取器)。 对于集合,不可变视图应使用Collections.unmodifiableXxx包装器公开。

public Collection<String> getCollectionOfString() {return Collections.unmodifiableCollection( collectionOfString );
}

对于数组,确保真正的不变性的唯一方法是提供副本,而不是返回对数组的引用。 从实际的角度来看,这可能是不可接受的,因为它在很大程度上取决于数组的大小,并可能给垃圾收集器带来很大压力。

public String[] getArrayOfStrings() {return Arrays.copyOf( arrayOfStrings, arrayOfStrings.length );
}

即使是这个很小的例子,也提供了一个很好的主意,即不变性还不是Java中的一等公民。 如果一个不可变的类具有引用另一个类实例的字段,那么事情就会变得非常复杂。 这些类也应该是不可变的,但是没有简单的方法可以强制执行。

有很多很棒的Java源代码分析器,例如FindBugsPMD ,它们可以通过检查代码并指出常见的Java编程缺陷来提供很多帮助。 这些工具是任何Java开发人员的好朋友。

7.匿名类

在Java 8之前的时代,匿名类是提供就地类定义和即时实例化的唯一方法。 匿名类的目的是减少样板,并提供简洁明了的方式将类表示为表达式。 让我们看一下在Java中产生新线程的典型老式方法:

package com.javacodegeeks.advanced.design;public class AnonymousClass {public static void main( String[] args ) {new Thread(// Example of creating anonymous class which implements// Runnable interfacenew Runnable() {@Overridepublic void run() {// Implementation here}}).start();}
}

在此示例中, Runnable接口的实现作为匿名类就地提供。 尽管匿名类存在一些限制,但使用它们的基本缺点是Java强制将其作为语言使用的语法结构非常冗长。 即使是最简单的不执行任何操作的匿名类,每次都至少需要编写5行代码。

new Runnable() {@Overridepublic void run() {}}

幸运的是,有了Java 8,lambda和功能接口,所有这些样板都将消失,最终使Java代码看起来非常简洁。

package com.javacodegeeks.advanced.design;public class AnonymousClass {public static void main( String[] args ) {new Thread( () -> { /* Implementation here */ } ).start();}
}

8.可见度

在本教程的第1部分“ 如何设计类和接口”中 ,我们已经讨论了Java可见性和可访问性规则。 在这一部分中,我们将再次回到该主题,但要涉及子类化。

修饰符 子类 其他所有人
上市 无障碍 无障碍 无障碍
受保护的 无障碍 无障碍 无法访问
<无修饰符> 无障碍 无法访问 无法访问
私人的 无法访问 无法访问 无法访问

表格1

不同的可见性级别允许或不允许这些类查看其他类或接口(例如,如果它们位于不同的程序包中或彼此嵌套)或子类查看和访问其父级的方法,构造函数和字段。

在下一节Inheritance中 ,我们将看到它的作用。

9.继承

继承是面向对象编程的关键概念之一,它是建立类关系的基础。 与可见性和可访问性规则结合使用,继承可以设计可扩展和可维护的类层次结构。

从概念上讲,Java中的继承是通过使用子类和extends关键字以及父类来实现的。 子类继承其父类的所有公共成员和受保护成员。 此外,如果子类都驻留在同一包中,则它们继承父类的包私有成员。 话虽如此,无论您要设计什么,保持类公开或对其子类公开的最小方法集都是非常重要的。 例如,让我们看一下Parent类及其子类Child以演示不同的可见性级别及其效果:

package com.javacodegeeks.advanced.design;public class Parent {// Everyone can see itpublic static final String CONSTANT = "Constant";// No one can access itprivate String privateField;// Only subclasses can access itprotected String protectedField;// No one can see itprivate class PrivateClass {}// Only visible to subclassesprotected interface ProtectedInterface {}// Everyone can call itpublic void publicAction() {}// Only subclass can call itprotected void protectedAction() {}// No one can call itprivate void privateAction() {}// Only subclasses in the same package can call itvoid packageAction() {}
}
package com.javacodegeeks.advanced.design;// Resides in the same package as parent class
public class Child extends Parent implements Parent.ProtectedInterface {@Overrideprotected void protectedAction() {// Calls parent's method implementationsuper.protectedAction();}@Overridevoid packageAction() {// Do nothing, no call to parent's method implementation}public void childAction() {this.protectedField = "value";}
}

继承本身就是一个非常大的主题,其中包含许多特定于Java的细微细节。 但是,有一些易于遵循的规则可以对保持类层次结构简洁有很大帮助。 在Java中,每个子类都可以覆盖其父类的任何继承的方法,除非将其声明为final (请参阅Final类和方法部分 )。

但是,没有特殊的语法或关键字来将方法标记为已重写,这可能会引起很多混乱。 这就是引入@Override批注的原因:每当您打算覆盖继承的方法时,请始终使用@Override批注进行指示。

Java开发人员在设计中经常面临的另一个难题是构建类层次结构(使用具体或抽象类)与接口实现。 强烈建议尽可能使用接口而不是类或抽象类。 接口轻巧得多,易于测试(使用模拟)和维护,并且使实现更改的副作用最小化。 许多高级编程技术(例如在标准Java库中创建类代理)都严重依赖于接口。

10.多重继承

与C ++和其他一些语言相比,Java不支持多重继承:在Java中,每个类都只有一个直接父级( Object类位于层次结构的顶部,正如我们在本教程的第2部分中已经知道的那样, 使用通用方法)。到所有对象 )。 但是,该类可以实现多个接口,因此,堆叠接口是在Java中实现(或模仿)多重继承的唯一方法。

package com.javacodegeeks.advanced.design;public class MultipleInterfaces implements Runnable, AutoCloseable {@Overridepublic void run() {// Some implementation here}@Overridepublic void close() throws Exception {// Some implementation here}
}

多个接口的实现实际上是非常强大的,但是重用实现的需求通常会导致深层次的类层次结构,这是克服Java中缺少多继承支持的一种方法。

public class A implements Runnable {@Overridepublic void run() {// Some implementation here}
}
// Class B wants to inherit the implementation of run() method from class A.
public class B extends A implements AutoCloseable {@Overridepublic void close() throws Exception {// Some implementation here}
}
// Class C wants to inherit the implementation of run() method from class A
// and the implementation of close() method from class B.
public class C extends B implements Readable {@Overridepublic int read(java.nio.CharBuffer cb) throws IOException {// Some implementation here}
}

依此类推...最近的Java 8版本通过引入默认方法在某种程度上解决了该问题。 由于使用默认方法,因此接口实际上已经开始不仅提供合同,而且还提供实现。 因此,实现这些接口的类也将自动继承这些实现的方法。 例如:

package com.javacodegeeks.advanced.design;public interface DefaultMethods extends Runnable, AutoCloseable {@Overridedefault void run() {// Some implementation here}@Overridedefault void close() throws Exception {// Some implementation here}
}// Class C inherits the implementation of run() and close() methods from the
// DefaultMethods interface.
public class C implements DefaultMethods, Readable {@Overridepublic int read(java.nio.CharBuffer cb) throws IOException {// Some implementation here}
}

请注意,多重继承是一种强大的工具,但同时又是一种危险的工具。 通常将众所周知的“死亡钻石”问题称为多重继承实现的基本缺陷,因此,敦促开发人员非常仔细地设计类层次结构。 不幸的是,具有默认方法的Java 8接口也正成为这些漏洞的受害者。

interface A {default void performAction() {}
}interface B extends A {@Overridedefault void performAction() {}
}interface C extends A {@Overridedefault void performAction() {}
}

例如,以下代码片段无法编译:

// E is not compilable unless it overrides performAction() as well
interface E extends B, C {
}

在这一点上,可以说Java作为一种语言总是试图逃避面向对象编程的极端情况,但是随着语言的发展,其中一些情况开始出现。

11.继承与组成

幸运的是,继承不是设计类的唯一方法。 许多开发人员认为比继承更好的另一种选择是组合。 这个想法很简单:这些类应该由其他类组成,而不是建立类层次结构。

让我们看一下这个例子:

public class Vehicle {private Engine engine;private Wheels[] wheels;// ...
}

Vehicle类由enginewheels (加上许多其他零件,为简单起见而保留)。 但是,可以说Vehicle类也是一种引擎,因此可以使用继承进行设计。

public class Vehicle extends Engine {private Wheels[] wheels;// ...
}

哪个设计决定是正确的? 一般准则称为IS-AHAS-A原则。 IS-A是继承关系:子类还满足父类规范以及父类的此类IS-A变体。 因此, HAS-A是组成关系:该类拥有(或HAS-A )属于它的对象。 在大多数情况下, HAS-A原理比IS-A更好,其原因有两个:

  • 设计可以更改的方式更加灵活
  • 该模型更加稳定,因为更改不会通过类层次结构传播
  • 与继承紧密关联父级及其子类的继承相比,该类及其组合之间的关联松散
  • 关于类的推理更加简单,因为所有相关性都包含在其中

但是,继承有其自己的位置,以不同的方式解决了实际的设计问题,因此不应忽略。 在设计面向对象的模型时,请牢记这两种选择。

12.封装

面向对象编程中的封装概念全是向外界隐藏实现细节(如状态,内部方法等)。 封装的好处是可维护性和易于更改。 内在细节类暴露的越少,开发人员对更改其内部实现的控制就越多,而不必担心破坏现有代码(如果您正在开发许多人使用的库或框架,这将是一个真正的问题)。

Java中的封装是使用可见性和可访问性规则实现的。 在Java中,最好不要使用getter和setter方法(如果未将字段声明为final )直接暴露字段,这是Java的最佳实践。 例如:

package com.javacodegeeks.advanced.design;public class Encapsulation {private final String email;private String address;public Encapsulation( final String email ) {this.email = email;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getEmail() {return email;}
}

此示例类似于Java语言中所谓的JavaBeans :通过遵循一组约定编写的常规Java类,其中一种仅允许使用getter和setter方法访问字段。

正如我们在“ 继承”部分中已强调的那样,请始终遵循封装原则,尝试使类公共契约保持最小。 无论什么都不应该是public ,而应该是private (或protected / package private ,这取决于您要解决的问题)。 从长远来看,它将带来回报,使您可以自由开发设计而无需引入重大更改(或至少将更改减至最少)。

13.期末课程和方法

在Java中,有一种方法可以防止该类被其他任何类继承:应该将其声明为final

package com.javacodegeeks.advanced.design;public final class FinalClass {
}

方法声明中使用相同的final关键字可防止所讨论的方法在子类中被覆盖。

package com.javacodegeeks.advanced.design;public class FinalMethod {public final void performAction() {}
}

没有通用的规则来决定类或方法是否应该是final 。 最终类和方法限制了可扩展性,并且很难预先考虑该类是否应该被子类化,或者方法是否应该被覆盖。 这对于库开发人员尤其重要,因为这样的设计决策可能会大大限制库的适用性。

Java标准库提供了一些final类的示例,其中最著名的是String类。 在早期阶段,已做出决定来主动防止任何开发人员尝试提出自己的“更好的”字符串实现。

14.接下来

在本教程的这一部分中,我们研究了Java中的面向对象设计概念。 我们还简要地介绍了基于合同的开发,介绍了一些功能概念,并了解了该语言如何随着时间演变。 在本教程的下一部分中,我们将讨论泛型以及泛型如何改变我们处理类型安全编程的方式。

15.下载源代码

这是关于如何设计类和接口的课程。

  • 您可以在此处下载源代码: advanced-java-part-3

翻译自: https://www.javacodegeeks.com/2015/09/how-to-design-classes-and-interfaces.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/358405.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HDU 3072 SCC Intelligence System

给出一个带权有向图&#xff0c;要使整个图连通。SCC中的点之间花费为0&#xff0c;所以就先缩点&#xff0c;然后缩点后两点之间的权值为最小边的权值&#xff0c;把这些权值累加起来就是答案。 1 #include <iostream>2 #include <cstdio>3 #include <algorith…

再见,Springboot和SpringCloud

Java中说到微服务肯定离不开Spring Boot和Spring Cloud&#xff0c;这两者到底有什么关系&#xff0c;什么是微服务&#xff0c;如果单纯的说SpringBoot&#xff0c;SpringCloud&#xff0c;都是不准确的&#xff0c;那应该怎么回答。官网对于Spring Boot的介绍Spring Boot mak…

通过暴露出来的OA和github信息拿Shell

本文转载于https://xz.aliyun.com/t/10392 记一次授权渗透测试 一&#xff1a;信息收集阶段 因为目标是学校&#xff0c;一般会去考虑收集学号&#xff0c;教工号。因为有的登陆点需要此类信息&#xff0c;且密码存在规律性&#xff08;身份证后六位&#xff0c;123456&#xf…

表格内容排序(js实现)

http://tablesorter.com/docs/转载于:https://www.cnblogs.com/sunflower627/p/4718688.html

手机上可以编程看代码的软件

以后大家会在路上看到很多人拿着手机,他不是在聊天,他有可能是运维工程师、也可能是算法开发、也可能是java开发,还可能是客户端开发,也可能是前端开发... 让你编程一直在路上,这到底是程序员的福音,还是码农的枷锁。 粉丝提问: 这里介绍几款可以在手机上编程的app,分…

给你的执行力马上充值

“执行力就是在既定的战略和愿景的前提下,组织对内外部可利用的资源进行综合协调,制定出可行性的战略,并通过有效的执行措施从而最终实现组织目标、达成组织愿景的一种力量。执行力是一个变量,不同的执行者在执行同一件事情的时候也会得到不同的结果。执行力不但因人而异,而且还…

性能,可伸缩性和活力

本文是我们学院课程中名为Java Concurrency Essentials的一部分 。 在本课程中&#xff0c;您将深入探讨并发的魔力。 将向您介绍并发和并发代码的基础知识&#xff0c;并学习诸如原子性&#xff0c;同步和线程安全之类的概念。 在这里查看 &#xff01; 目录 1.简介 2.表现…

Java 压缩解压字符串(支持中文)

public static void main(String[] args) throws Exception{ String str "xflush3.0个人感觉最大的特点就是监控配置非常灵活&#xff0c;从日志的格式定义、收集、配置&#xff0c;都可以自定义&#xff1b;这样对于老应用的打点日志&#xff0c;不需要关心规则的定义就可…

BurpSuite v2021.8.2安装使用

文章前言 几个月之前&#xff0c;Burpsuit官方发布了BurpSuite v2021.8.2&#xff0c;但是迟迟没有时间来试试手&#xff0c;正好借着这次调休的时间来写写文章&#xff0c;顺便更新一下Burpsuite 软件下载 天翼云盘 极速安全 家庭云|网盘|文件备份|资源分享 软件安装 Step 1&a…

程序员赚钱资源汇总,结合自己亲身经历

知识计算机知识深入理解计算机系统-必修课&#xff0c;NB学校的NB课程的NB教材代码大全-&#xff08;不要被这个名字吓到&#xff0c;英文叫做 Code complete&#xff09;微软的书&#xff0c;几乎可以当作是软件工程的百科全书。很少有人完全精通甚至完成这本书中所有部分的学…

Hive高级用法汇总

1. 根据字符串分割实现一行变多行 关键字&#xff1a;LATERAL VIEW&#xff0c; explode&#xff0c;split SELECT ad_time_slice_index, SUM(impression_count) FROM base_tracking_logs LATERRAL VIEW EXPLODE(SPLIT(ad_time_slices,\\,)) adalias AS ad_time_slice_index WH…

Agrona的Threadsafe堆外缓冲区

这篇博客文章解释了我们如何为线程安全操作轻松提供对堆内存的访问&#xff0c;从而继续了我在Agrona库上进行的系列文章 。 在继续进行之前&#xff0c;我可能应该警告一下&#xff0c;这是一个相当高级的主题&#xff0c;并且我不会尝试解释诸如内存屏障之类的概念&#xff0…

逍遥模拟器配置burpsuite抓包环境

电脑与逍遥模拟器处于同一网段&#xff0c;在burpsuite中设置代理&#xff1a; 之后在逍遥模拟器中设置网络代理 之后直接下载下面的证书并且将其拖放到逍遥模拟器中&#xff1a; 证书下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1qJmcKcVj3NqmrWKf6zb83g …

在线演示一下HTML的各种实例,打发无聊的时间

这段时间入职了一家外包公司,比较闲,好像是去驻场开发做金融保险的项目,我应聘的是前端工程师的岗位,要准备刷题,听说考的范围比较广,我是电子商务专业的,本身学的就比较广,没事做做html的实例打发无聊的时间。有兴趣的可以关注我的公众号:电商程序员。各种资源都有,…

OC本学习笔记Foundation框架NSString与NSMutableString

一、NSString与NSMutableString 相信大家对NSString类都不陌生。它是OC中提供的字符串类。它的对象中的字符串都是不可变的&#xff0c;而它的子类NSMutableString类的对象中的字符串就是可变的。什么是可变与不可变呢&#xff1f;二者的差别就是在已经创建的一个字符串…

phpMyAdmin渗透利用总结

phpMyAdmin渗透利用总结 前言 总结一下常见的phpmyadmin的漏洞利用姿势 简介 phpMyAdmin 是一个以PHP为基础&#xff0c;以Web-Base方式架构在网站主机上的MySQL的数据库管理工具&#xff0c;让管理者可用Web接口管理MySQL数据库。借由此Web接口可以成为一个简易方式输入繁杂…

SQL之条件判断专题

Case when (case when 情况1 then 结果1 when 情况1 then 结果1 else &#xff0b;剩余结果 end ) 列名 IF表达式 IF(判断内容&#xff0c;0&#xff0c;1) SELECT IF( sex1&#xff0c;男 &#xff0c;女 )sex from student IFNULL表达式 IF(判断内容&#xff0c;x) 假如判…

使用所有对象通用的方法

本文是我们名为“ 高级Java ”的学院课程的一部分。 本课程旨在帮助您最有效地使用Java。 它讨论了高级主题&#xff0c;包括对象创建&#xff0c;并发&#xff0c;序列化&#xff0c;反射等。 它将指导您完成Java掌握的过程&#xff01; 在这里查看 &#xff01; 目录 1.简…

前端工程师面经——概述及面试技巧加考点篇(一)

这段时间受到疫情的影响,本身做java开发的,面试了入职了一个外包公司的前端岗位,入职属于驻场开发的那种,前几周基本没啥事,一般经理会让你刷题,到了驻场那边需要机试过关才能在那边开发,这边在牛客网,LeetCode等平台找点前端的题做一做顺便记录,仅供参考,那边做的是…

Struts2漏洞和Struts Scan工具实战

一、Apache Struts 2漏洞背景 1.漏洞详情 2017年3月6日&#xff0c;Apache Struts 2被曝存在远程命令执行漏洞。在使用基于Jakarta插件的文件上传功能条件下&#xff0c;恶意用户可以通过修改HTTP请求头中的Content-Type值构造恶意代码&#xff0c;在服务器上执行系统命令&…