博客

  • CSS3 Flex布局详解

    Flex 弹性布局

    通过弹性盒子模型,可以轻松地创建自适应浏览器窗口的流动布局以及自适应字体大小的弹性布局,使得响应式布局的实现更加容易。

    在Flex布局中,容器是定义了Flex布局的元素,而项目是容器的子元素。

    Flex布局的几个关键概念包括

    • 主轴和交叉轴。Flex布局默认包含两根轴,水平的主轴和垂直的交叉轴。主轴的开始位置称为main start,结束位置称为main end;交叉轴的开始位置称为cross start,结束位置称为cross end。项目默认沿主轴排列。
    • 项目的尺寸。单个项目占据的主轴空间称为main size,占据的交叉轴空间称为cross size。

    Flex布局的常用属性包括

    • flex-direction 该属性定义了主轴的方向,默认为row(水平方向),row-reverse(水平方向,起点在右端),column(垂直方向),或column-reverse(垂直方向,起点在下端)。
    • justify-content 该属性定义了项目在主轴上的对齐方式,包括flex-start(起点对齐)、flex-end(终点对齐)、center(居中对齐)和space-between(两端对齐,项目之间等间距)等。
    • align-items 该属性定义了项目在交叉轴上的对齐方式,包括stretch(默认,高度占满整个容器)、center(垂直居中)等。
    • flex-wrap 该属性定义了项目是否换行,默认为nowrap(不换行),wrap(换行,第一行在上方),或wrap-reverse(换行,第一行在下方)。
    • align-content 该属性定义了多行项目在交叉轴上的对齐方式。
    • flex-grow 定义子元素的放大比例
    • flex-shrink 定义子元素的缩小比例
    • flex-basis 定义自元素的宽度,替代width属性
    • flex 复合属性,flex-grow、flex-shrink、flex-basis的简写
    • flex-flow 复合属性,flex-direction、flex-wrap
    • order 定义子元素的排列顺序

    这些属性允许开发者以更灵活的方式控制项目的布局,使其能够适应不同的屏幕大小和设备方向。

  • CSS3 中-webkit-text-size-adjust 详解

    -webkit-text-size-adjust 是一个 CSS 属性,用于指定文本大小是否应该根据设备的屏幕大小进行调整。这个属性主要是为了移动设备设计的,因为用户可能会改变他们浏览器的字体大小设置。

    该属性可以设置为以下值:

    • none:文本大小不会根据屏幕大小调整。
    • auto:文本大小会根据屏幕大小调整。这是默认值。
    • initial:设置为浏览器默认的文本大小。
    /* 禁止文本大小自动调整 */
    .element {
      -webkit-text-size-adjust: none;
      text-size-adjust: none;
    }
     
    /* 启用文本大小自动调整 */
    .element {
      -webkit-text-size-adjust: auto;
      text-size-adjust: auto;
    }
     
    /* 设置为浏览器默认的文本大小 */
    .element {
      -webkit-text-size-adjust: initial;
      text-size-adjust: initial;
    }

    在实际使用中,你可能只需要设置 -webkit-text-size-adjust: none; 来确保你的网站在 iOS 设备上的 Safari 浏览器中文本大小不会根据设备的屏幕大小调整。其他浏览器,如 Chrome 和 Firefox,也支持这个属性,但可能需要前缀,如 -moz-text-size-adjust 用于 Firefox。

  •  Java面向对象

    一个模板,描述一类对象的行为和状态

    • 局部变量
    • 成员变量
    • 类变量:必现声明为static类型
    • 一个源文件只能有一个public类
    • 一个源文件可以有多个非public类型
    • 源文件名称应该和public类的类名一致
    • 一个类定义在某个包中,那么package语句应该在源文件的首行
    • 如果源文件包含​import​语句,那么应该放在​package​语句和类定义之间。如果没有​package​语句,那么​import​语句应该在源文件中最前面。
    • import​语句和​package​语句对源文件中定义的所有类都有效。在同一源文件中,不能给不同的类不同的包声明。

    对象

    类的实例,有状态和行为

    Java 包

    包主要用来对类和接口进行分类

    Import语句

    在 Java 中,如果给出一个完整的限定名,包括包名、类名,那么 Java 编译器就可以很容易地定位到源代码或者类。​Import​ 语句就是用来提供一个合理的路径,使得编译器可以找到某个类。

    Java 修饰符

    访问修饰符

    可以使用访问控制符来保护对类、变量、方法和构造方法的访问

    • 默认的,也称为 default,在同一包内可见,不使用任何修饰符。
    • 私有的,以 private 修饰符指定,在同一类内可见。
    • 公有的,以 public 修饰符指定,对所有类可见。
    • 受保护的,以 protected 修饰符指定,对同一包内的类和所有子类可见。
    1. 接口里的变量都隐式声明为​public static final​,而接口里的方法默认情况下访问权限为 ​public
    2. 类和接口不能声明为 private
    3. 声明为私有访问类型的变量只能通过类中公共的 getter 方法被外部类访问。
    4. Private 访问修饰符的使用主要用来隐藏类的实现细节和保护类的数据。
    5. 由于类的继承性,类所有的公有方法和变量都能被其子类继承。
    6. Protected 访问修饰符不能修饰类和接口,方法和成员变量能够声明为 protected,但是接口的成员变量和成员方法不能声明为 protected

    访问控制和继承

    • 父类中声明为 public 的方法在子类中也必须为 public。
    • 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public。不能声明为 private。
    • 父类中声明为 private 的方法,不能够被继承

    非访问修饰符

    static

    修饰符,用来创建类方法和类变量。

    静态变量

    static 关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。静态变量也被称为类变量。

    局部变量不能被声明为static变量。

    静态方法

    static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。

    final 修饰符

    用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。

    final 变量

    final 变量能被显式地初始化并且只能初始化一次。被声明为final的对象的引用不能指向不同的对象。但是 final 对象里的数据可以被改变。也就是说 final 对象的引用不能改变,但是里面的值可以改变。

    final 修饰符通常和 static 修饰符一起使用来创建类常量。

    final 方法

    类中的 Final 方法可以被子类继承,但是不能被子类修改。

    声明 final 方法的主要目的是防止该方法的内容被修改。

    final 类

    final 类不能被继承,没有类能够继承 final 类的任何特性。

    abstract

    修饰符,用来创建抽象类和抽象方法。

    抽象类

    抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充

    一个类不能同时被 abstract 和 final 修饰。如果一个类包含抽象方法,那么该类一定要声明为抽象类,否则将出现编译错误。

    抽象类可以包含抽象方法和非抽象方法。

    抽象方法

    抽象方法是一种没有任何实现的方法,该方法的的具体实现由子类提供。抽象方法不能被声明成 final 和 static。

    任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。

    如果一个类包含若干个抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法。

    抽象方法的声明以分号结尾,例如:public abstract sample();

    synchronized

    修饰符 ,主要用于线程的编程

    synchronized 关键字声明的方法同一时间只能被一个线程访问。Synchronized 修饰符可以应用于四个访问修饰符

        public synchronized void showDetails(){
                .......
        } 

    volatile

    修饰符,主要用于线程的编程。

    volatile 修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。一个 volatile 对象引用可能是 null。

            public class MyRunnable implements Runnable
            {
                private volatile boolean active;
                public void run()
                {
                    active = true;
                    while (active) // line 1
                    {
                        // 代码
                    }
                }
                public void stop()
                {
                    active = false; // line 2
                }
            }

    transient 修饰符

    序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机 (JVM) 跳过该特定的变量。

    该修饰符包含在定义变量的语句中,用来预处理类和变量的数据类型。

    实例:

        public transient int limit = 55;   // will not persist
        public int b; // will persist

    Java 继承

    Java 只支持单继承(继承基本类和抽象类),但是我们可以用接口来实现(多继承接口来实现)。

    继承中最常使用的两个关键字是 extends 和 implements 。

    extends

    通过 extends 关键字可以申明一个类是继承另外一个类而来的

    IS-A 关系

    IS-A 就是说:一个对象是另一个对象的一个分类。

    implements

    implements 关键字在类继承接口的情况下使用,这种情况不能使用关键字 extends。

    HAS-A 关系

    HAS-A 代表类和它的成员之间的从属关系。这有助于代码的重用和减少代码的错误。

    Java 重写(Override)与重载(Overload)

    重写(Override)

    重写是子类对父类的允许访问的方法的实现过程进行重新编写!返回值和形参都不能改变。即外壳不变,核心重写!

    重写的好处在于子类可以根据需要,定义特定于自己的行为。

    也就是说子类能够根据需要实现父类的方法。

    在面向对象原则里,重写意味着可以重写任何现有方法。

    方法重写的规则

    • 参数列表与被重写方法的参数列表必须完全相同。
    • 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类
    • 子类方法的访问权限必须大于或等于父类方法的访问权限。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。
    • 父类的成员方法只能被它的子类重写。
    • 声明为 final 的方法不能被重写。
    • 声明为 static 的方法不能被重写,但是能够被再次声明。
    • 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
    • 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
    • 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
    • 构造方法不能被重写。
    • 如果不能继承一个方法,则不能重写这个方法。

    Super 关键字的使用

    当需要在子类中调用父类的被重写方法时,要使用 super 关键字

    重载 (Overload)

    重载 (overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型呢?可以相同也可以不同。

    每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。

    最常用的地方就是构造器的重载。

    重载规则

    • 被重载的方法必须改变参数列表;
    • 被重载的方法可以改变返回类型;
    • 被重载的方法可以改变访问修饰符;
    • 被重载的方法可以声明新的或更广的检查异常;
    • 方法能够在同一个类中或者在一个子类中被重载。
    • 无法以返回值类型作为重载函数的区分标准。

    重写与重载之间的区别

    区别点重载方法重写方法
    参数列表必须修改一定不能修改
    返回类型可以修改一定不能修改
    异常可以修改可以减少活删除,一定不能抛出新的或者更广的异常
    访问可以修改一定不能做更严格的限制

    总结

    方法的重写 (Overriding) 和重载 (Overloading) 是 java 多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。

    • 方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载 (Overloading)。
    • 方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写 (Overriding)。
    • 方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。

    Java 多态

    多态是同一个行为具有多个不同表现形式或形态的能力。
    多态性是对象多种表现形式的体现。

    简单的例子

    public interface Vegetarian{}
    public class Animal{}
    public class Deer extends Animal implements Vegetarian{}

    因为Deer类具有多重继承,所以它具有多态性。以上实例解析如下:

    • 一个 Deer IS-A(是一个) Animal
    • 一个 Deer IS-A(是一个) Vegetarian
    • 一个 Deer IS-A(是一个) Deer
    • 一个 Deer IS-A(是一个)Object

    Java 抽象类

    抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。

    由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。

    父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。

    抽象方法

    Abstract关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。

    抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。

    声明抽象方法会造成以下两个结果:

    • 如果一个类包含抽象方法,那么该类必须是抽象类。
    • 任何子类必须重写父类的抽象方法,或者声明自身为抽象类。

    Java 封装

    封装是指,一种将抽象性函式接口的实作细节部份包装、隐藏起来的方法。

    封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。

    要访问该类的代码和数据,必须通过严格的接口控制。

    封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。

    适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。

    最常见的例子是:getter 和 setter 方法

    Java 接口

    在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。

    接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。

    除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。

    接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在Java中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。

    接口与类相似点

    • 一个接口可以有多个方法。
    • 接口文件保存在.java结尾的文件中,文件名使用接口名。
    • 接口的字节码文件保存在.class结尾的文件中。
    • 接口相应的字节码文件必须在与包名称相匹配的目录结构中。

    接口与类的区别

    • 接口不能用于实例化对象。
    • 接口没有构造方法。
    • 接口中所有的方法必须是抽象方法。
    • 接口不能包含成员变量,除了static和final变量。
    • 接口不是被类继承了,而是要被类实现。
    • 接口支持多重继承。

    接口特性

    • 接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
    • 接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键子。
    • 接口中的方法都是公有的。

    重写接口

    重写接口中声明的方法时,需要注意以下规则:

    • 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
    • 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。
    • 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。

    实现接口

    在实现接口的时候,也要注意一些规则:

    • 一个类可以同时实现多个接口。
    • 一个类只能继承一个类,但是能实现多个接口。
    • 一个接口能继承另一个接口,这和类之间的继承比较相似。

    接口的继承

    一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用extends关键字,子接口继承父接口的方法。

    接口的多重继承

    在Java中,类的多重继承是不合法,但接口允许多重继承。

    在接口的多重继承中extends关键字只需要使用一次,在其后跟着继承接口。

    标记接口

    最常用的继承接口是没有包含任何方法的接口。

    标识接口是没有任何方法和属性的接口.它仅仅表明它的类属于一个特定的类型,供其他代码来测试允许做一些事情。

    标识接口作用:简单形象的说就是给某个对象打个标(盖个戳),使对象拥有某个或某些特权。

    package java.util;
    public interface EventListener
    {}

    标记接口主要用于以下两种目的:

    • 建立一个公共的父接口:
      正如EventListener接口,这是由几十个其他接口扩展的Java API,你可以使用一个标记接口来建立一组接口的父接口。例如:当一个接口继承了EventListener接口,Java虚拟机(JVM)就知道该接口将要被用于一个事件的代理方案。
    • 向一个类添加数据类型:
      这种情况是标记接口最初的目的,实现标记接口的类不需要定义任何接口方法(因为标记接口根本就没有方法),但是该类通过多态性变成一个接口类型

    Java 包(package)

    为了更好地组织类,Java提供了包机制,用于区别类名的命名空间。

    Java使用包(package)这种机制是为了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举(enumerations)和注释(annotation)等

    package(包)的作用是把不同的java程序分类保存,更方便的被其他java程序调用。

    一个包(package)可以定义为一组相互联系的类型(类、接口、枚举和注释),为这些类型提供访问保护和命名空间管理的功能。

    包的作用

    • 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
    • 如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
    • 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

    import关键字

    在 java 源文件中 import 语句应位于 package 语句之后,所有类的定义之前,可以没有,也可以有多条,其语法格式为:

    import package1[.package2…].(classname|*);

    package的目录结构

    类放在包中会有两种主要的结果:

    • 包名成为类名的一部分,正如我们前面讨论的一样。
    • 包名必须与相应的字节码所在的目录结构相吻合。