Глубокое понимание статического ключевого слова

Java

Прежде чем я начну говорить о статике, я хочу показать вам интересный фрагмент кода:

public class Test {
     
    static{
        System.out.println("test static 1");
    }
  
    static{
        System.out.println("test static 2");
    }
    
    public static void main(String[] args) {
         
    }
}

Прочитав программу, Сяобай Туншо сказал: Что это? В основном методе ничего нет, что он может запустить? Блогер ты звезда...

运行结果:
test static 1
test static 2

Xiaobai Children's Shoes: Что... что... блогер, что я сказал, я ничего не сказал...

На самом деле, если вы понимаете приведенный выше код, вы его поймете, но если вы его не понимаете, вы его не поймете, потому что приведенный выше код включает загрузку классов JVM! Конечно, за рамками этого поста в блоге, если вы заинтересованы в понимании описанной выше процедуры, этот пост может быть вам полезен.

Не переворачивайте, эта статья определенно даст вам глубокое понимание загрузки классов Java и анализа исходного кода ClassLoader [JVM, часть 2]

1. Основной смысл статичного существования

Основное значение статики заключается в создании переменных или методов предметной области, которые не зависят от конкретных объектов.так что вы можете использовать свойства и вызывать методы даже без создания объекта!

Другая ключевая функция ключевого слова static заключается в том, чтоИспользуется для формирования статических блоков кода для оптимизации производительности программы.. Блок STATIC можно разместить в любом месте класса, и в классе есть несколько блоков STATIC. При первоначальной загрузке класса каждый статический блок выполняется в том же порядке, что и статический блок, и только один раз.

Почему статический блок может использоваться для оптимизации производительности программы, является из-за его характеристик: он будет выполнен только после того, как класс загружен. Поэтому во многих случаях некоторые операции инициализации, которые нужно выполнить только один раз, помещаются в статический код код.

2. Уникальность статики

1. Модифицируемая static переменная или метод — это любой объект, независимый от класса, то есть эти переменные и методыНе принадлежит ни одному объекту экземпляра, но совместно используется объектами экземпляра класса.

Как вы понимаете фразу «совместно используемую объектами-экземплярами класса»? Другими словами, статический член класса принадлежит всем [Каждый ссылается на несколько экземпляров объекта этого класса. Все мы знаем, что класс может создавать несколько экземпляров! ], который является общим для всех объектов класса, в отличие от переменных-членов, которые являются частными [self относится к одному экземпляру объекта этого класса]... Я думаю, что то, что я сказал, очень популярно, понимаете?

2. Когда класс загружается в первый раз, будет загружена статическая измененная часть, и она будет загружена и инициализирована только при первом использовании класса.Обратите внимание, что это первый раз, когда он используется для инициализации. быть переназначаемым.

3. Значение статической переменной выделяется при загрузке класса и не будет повторно выделяться при последующем создании объекта класса. Если вы присваиваете значение, вы можете присваивать его произвольно!

4. Переменные или методы, измененные с помощью static, имеют приоритет над объектами, то есть когда класс загружен, к нему можно получить доступ, даже если объект не создан.

3. Сценарии статических приложений

Поскольку static используется объектами-экземплярами класса, поэтому, еслиПеременная-член является общей для всех объектов, тогда эта переменная-член должна быть определена как статическая переменная..

Таким образом, более распространенными сценариями статического приложения являются:

1. Изменить переменные участников 2. Модифицированные методы участников 3. Статический код код 4. Модифицированные классы [Только внутренние классы могут быть изменены только, то есть статические внутренние классы] 5. Статический путеводитель

Вышеупомянутые сценарии применения будут обсуждаться в следующих разделах...

4. Концепция статических переменных и переменных экземпляра

статическая переменная: Статические измененные переменные-члены называются статическими переменными [также называемыми переменными класса], и статические переменные принадлежат классу, а не объекту.

переменная экземпляра: Переменная-член, которая не изменяется с помощью static, называется переменной экземпляра, а переменная экземпляра — это объект экземпляра, принадлежащий этому классу.

Еще одно замечание:static не разрешено изменять локальные переменные, не спрашивайте меня, что спрашивать, потому что java оговаривает!

5. Разница между статическими переменными и переменными экземпляра

статическая переменная: Поскольку статические переменные не принадлежат никаким объектам-экземплярам, ​​они принадлежат классам, поэтому в памяти находится только одна копия.При загрузке класса JVM выделяет место в памяти для статических переменных только один раз.

переменная экземпляра: Каждый раз, когда объект создается, для каждого объекта выделяется место в памяти переменных-членов.Переменные экземпляра принадлежат объектам-экземплярам.В памяти, когда объект создается несколько раз, есть несколько переменных-членов.

Я считаю, что ваш IQ выше, чем у Ичуня, и вы должны быть в состоянии понять приведенные выше слова. Примеры, приведенные ниже, предназначены исключительно для развлечения, и вам не нужно их читать, если вы их понимаете. Примеры ниже приведены только для справки и предназначены только для развлекательных целей. Вы можете пропустить их, если вы спешите!

Как понять это? Проведем аналогию... Например, программист Сяо Ван - относительно нежный и солнечный мальчик. В этот день 1024 года начальнику делать нечего, поэтому ему приходится тянуть программиста Сяо Вана играть. Как играть? Босс и Сяо Ван держат по кухонному ножу. Правила очень просты. Они причиняют друг другу боль. Один человек берет нож, ты берешь нож, я беру нож... В начале игры босс ничего не говорит, только вскакивает и берет нож, а программист Сяо Ван ничего не говорит.я не говорил что бэкхенд был просто рубилкой чтобы вернуться.в это время босс сошел с ума , его глаза были слишком большими, и он подскочил с другим ножом.В это время программист Сяо Ван не осмелился дать отпор, поэтому он этого не сделал. Неожиданно босс становился все более и более свирепым, а левый и правый слеши заняли около получаса.... Программист Сяо Ван никогда не сопротивлялся, потому что Сяо Ван знает, что он босс...

Этот программист Сяо Ван вернется к боссу только тогда, когда босс впервые взмахнет ножом, и тогда он не будет сопротивляться.В это время мы рассматриваем программиста Сяо Вана как статическую переменную, и босс помахал Сяо Ван в первый раз. Нож рассматривается как загрузка класса, и возвращение Сяо Вана к боссу рассматривается как выделение памяти, а круглый процесс одного человека, один нож рассматривается как процесс загрузки класса. После этого, каждый нож босса рассматривается как создание объекта.

Соответственно, значение статической переменной выделяется при первой загрузке класса и не будет переназначаться при последующем создании объекта класса.

После этого босс получил ножевое ранение и год пролежал в больнице.Первое, что он сделал, когда выписался из больницы и вернулся в компанию, это вытащил программиста Ичуня поиграть.Босс этого не знал. У Ичуня есть кухонный нож. Как только блогер Ичунь взял кухонный нож, он был застигнут врасплох подпрыгнувшим боссом. Программист Ичунь издал болезненный крик. Вспыльчивый программист Ичунь еще не закончил, и когда он в то же время, это было для босса.Одна косая черта, затем босс вскочил и еще одна косая черта, программист Ичунь хлопнул еще одну косую черту, босс вскочил и еще одну косую черту, программист Ичунь хлопнул еще одну косую черту, пока босс не "не останавливай программиста Ичуня, он не останавливался, потому что программист Ичунь знает, что если он покажет свой гнев, то посмеет прикоснуться к нему, когда тот раздражителен. Должны быть несколько старых утюгов, которые знают...

Программист Ичунь похож на переменные экземпляра.Каждый раз, когда создается объект, для каждого объекта выделяется место в памяти переменной-члена.Так же, как босс приходит с ножом, программист Ичунь возвращает вот такой нож...

6. Два способа доступа к статическим переменным и переменным экземпляра

Все мы знаем, что статические переменные относятся к этому классу, а не к объектам, статические не зависят от объектов.

Но вы не подумали об этом: хотя статические переменные-члены не зависят от объектов, это не означает, что к ним нельзя получить доступ через объекты.Все статические методы и статические переменные могут быть доступны через объекты [до тех пор, пока права доступа разрешены достаточно ], неважно, если вы не понимаете, подойдите к коду, чтобы понять

public class StaticDemo {

        static int value = 666;

        public static void main(String[] args) throws Exception{
            new StaticDemo().method();
        }

        private void method(){
            int value = 123;
            System.out.println(this.value);
        }

}

Угадай результат, я думаю, твой результат 123, ха-ха? фактически

运行结果: 666

Вернитесь назад и еще раз насладитесь приведенным выше отрывком, и вы сможете быть очень объективным и ясным.Если у вас есть такая идея, это использование не рекомендуется!

Итак, подытожим два способа доступа к статическим переменным и переменным экземпляра:

статическая переменная:

classname.static переменная

переменная object.static (не рекомендуется)

статический метод:

classname.static метод

метод object.static (устарел)

7, статический метод

Метод статической модификации также называется статическим методом. Я не знаю, нашли ли вы его. На самом деле, статический статический метод, с которым мы больше всего знакомы, является основным методом ~ Детская обувь Сяобай: ​​О, кажется, это так. правда~. Поскольку статический метод не принадлежит ни одному объекту-экземпляру, this относится к текущему объекту, потому что статический метод static не принадлежит ни одному объекту, поэтому об этом говорить не приходится.

Еще один момент:Конструктор не является статическим методом!

8, статический статический кодовый блок

Давайте сначала посмотрим на программу, чтобы увидеть, освоили ли вы блок статического кода.Следующее отношение наследования кода программыBaseThree --> BaseTwo --> BaseOne

Класс BaseOne

package com.gx.initializationblock;

public class BaseOne {

    public BaseOne() {
        System.out.println("BaseOne构造器");
    }

    {
        System.out.println("BaseOne初始化块");
        System.out.println();
    }

    static {
        System.out.println("BaseOne静态初始化块");

    }

}

Класс BaseTwo

package com.gx.initializationblock;

public class BaseTwo extends BaseOne {
    public BaseTwo() {
        System.out.println("BaseTwo构造器");
    }

    {
        System.out.println("BaseTwo初始化块");
    }

    static {
        System.out.println("BaseTwo静态初始化块");
    }
}

Класс BaseThree

package com.gx.initializationblock;

public class BaseThree extends BaseTwo {
    public BaseThree() {
        System.out.println("BaseThree构造器");
    }

    {
        System.out.println("BaseThree初始化块");
    }

    static {
        System.out.println("BaseThree静态初始化块");
    }
}

Тестовый класс demo2

package com.gx.initializationblock;

/*
     注:这里的ABC对应BaseOne、BaseTwo、BaseThree 
 * 多个类的继承中初始化块、静态初始化块、构造器的执行顺序
     在继承中,先后执行父类A的静态块,父类B的静态块,最后子类的静态块,
     然后再执行父类A的非静态块和构造器,然后是B类的非静态块和构造器,最后执行子类的非静态块和构造器
 */
public class Demo2 {
    public static void main(String[] args) {
        BaseThree baseThree = new BaseThree();
        System.out.println("-----");
        BaseThree baseThree2 = new BaseThree();

    }
}

результат операции

BaseOne静态初始化块
BaseTwo静态初始化块
BaseThree静态初始化块
BaseOne初始化块

BaseOne构造器
BaseTwo初始化块
BaseTwo构造器
BaseThree初始化块
BaseThree构造器
-----
BaseOne初始化块

BaseOne构造器
BaseTwo初始化块
BaseTwo构造器
BaseThree初始化块
BaseThree构造器

Что касается детской обуви, чей результат выполнения блока статического кода не очень ясен, обратитесь к этой статье за ​​подробностями.Статические статические блоки кода и порядок выполнения между блоками кода

Вышеупомянутое просто для того, чтобы вы знали порядок выполнения между блоками кода, чего явно недостаточно.Статические блоки кода обычно используются для инициализации статических переменных, таких как определение классов перечисления.Код выглядит следующим образом:

public enum WeekDayEnum {
    MONDAY(1,"周一"),
    TUESDAY(2, "周二"),
    WEDNESDAY(3, "周三"),
    THURSDAY(4, "周四"),
    FRIDAY(5, "周五"),
    SATURDAY(6, "周六"),
    SUNDAY(7, "周日");
 
    private int code;
    private String desc;
 
    WeekDayEnum(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }
 
    private static final Map<Integer, WeekDayEnum> WEEK_ENUM_MAP = new HashMap<Integer, WeekDayEnum>();
 
    // 对map进行初始化
    static {
        for (WeekDayEnum weekDay : WeekDayEnum.values()) {
            WEEK_ENUM_MAP.put(weekDay.getCode(), weekDay);
        }
    }
 
    public static WeekDayEnum findByCode(int code) {
        return WEEK_ENUM_MAP.get(code);
    }
 
    public int getCode() {
        return code;
    }
 
    public void setCode(int code) {
        this.code = code;
    }
 
    public String getDesc() {
        return desc;
    }
 
    public void setDesc(String desc) {
        this.desc = desc;
    }
}&emsp;

Конечно, не только аспект перечисления, но и знакомый шаблон singleton также использует статические блоки кода, как показано ниже:

public class Singleton {
    private static Singleton instance;
 
    static {
        instance = new Singleton();
    }
 
    private Singleton() {}
 
    public static Singleton getInstance() {
        return instance;
    }
}

9. Отличие статических переменных от обычных переменных

Статические переменные также называются статическими переменными.Разница между статическими переменными и нестатическими переменными заключается в том, что статические переменные являются общими для всех объектов и имеют только одну копию в памяти, которая будет инициализирована тогда и только тогда, когда класс загружается впервые. Нестатические переменные принадлежат объекту и инициализируются при создании объекта.Существует несколько копий, и копии, принадлежащие каждому объекту, не влияют друг на друга.

Другой момент заключается в том, что порядок инициализации статических переменных-членов инициализируется в том порядке, в котором они определены.

10. Статический внутренний класс

Существует одно из самых больших различий между статическими внутренними классами и нестатическими внутренними классами.Мы знаем, что нестатические внутренние классы будут неявно сохранять ссылку после компиляции, которая указывает на среду, в которой она была создана, но статические внутренние классы этого не делают. , нет. Без этой ссылки это означает:

1. Его создание не должно опираться на создание периферийных классов. 2. Он не может использовать какие-либо нестатические переменные-члены и методы окружающего класса.

Пример кода (статический внутренний класс реализует шаблон singleton)

public class Singleton {
    
   // 声明为 private 避免调用默认构造方法创建对象
    private Singleton() {
    }
    
   // 声明为 private 表明静态内部该类只能在该 Singleton 类中被访问
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getUniqueInstance() {
        return SingletonHolder.INSTANCE;
    }
}

когдаSingletonКогда класс загружается, статический внутренний классSingletonHolderне загружается в память. только при звонкеgetUniqueInstance()метод запускаSingletonHolder.INSTANCEВремяSingletonHolderбудет загружен и инициализирован в это времяINSTANCEэкземпляр, а JVM гарантирует, чтоINSTANCEСоздан только один раз.

Этот подход не только имеет преимущество отложенной инициализации, но также обеспечивает поддержку безопасности потоков с помощью JVM.

11. Пакет статических направляющих

Статический формат пакета импорта:import static

Эти два ключевых слова можно использовать вместе, чтобы указать импорт указанных статических ресурсов в класс, и вам не нужно использовать имя класса для вызова статических членов в классе, вы можете напрямую использовать статические переменные-члены и методы-члены в класс

//  Math. --- 将Math中的所有静态资源导入,这时候可以直接使用里面的静态方法,而不用通过类名进行调用
//  如果只想导入单一某个静态方法,只需要将换成对应的方法名即可
 
import static java.lang.Math.;
//  换成import static java.lang.Math.max;具有一样的效果
 
public class Demo {
	public static void main(String[] args) {
 
		int max = max(1,2);
		System.out.println(max);
	}
}

Пакет статического импорта действительно может сэкономить немного кода при написании кода и может напрямую вызывать статические члены в нем, но это повлияет на читабельность кода, поэтому обычно не рекомендуется использовать его в разработке.

12. Статические меры предосторожности

1. Статический может получить доступ только к статическому. 2. Нестатические могут обращаться как к нестатическим, так и к статическим.

13. Связь между final и static

На этом статью следовало бы закончить, но употребление статики всегда неотделимо от слова финал.Их можно сказать, что они связаны и часто встречаются.Я думаю, что об этом все же необходимо рассказать, так что давайте взглянем на следующую программу.

package Demo;

class FinalDemo {
    public final double i = Math.random();
    public static double t = Math.random();
}

public class DemoDemo {
    public static void main(String[] args) {

        FinalDemo demo1 = new FinalDemo();
        FinalDemo demo2 = new FinalDemo();
        System.out.println("final修饰的  i=" + demo1.i);
        System.out.println("static修饰的 t=" + demo1.t);
        System.out.println("final修饰的  i=" + demo2.i);
        System.out.println("static修饰的 t=" + demo2.t);

        System.out.println("t+1= "+ ++demo2.t );
//      System.out.println( ++demo2.i );//编译失败
      }
}
运行结果:
	final修饰的  i=0.7282093281367935
	static修饰的 t=0.30720545678577604
	final修饰的  i=0.8106990945706758
	static修饰的 t=0.30720545678577604
	t+1= 1.307205456785776

Статически измененная переменная не изменяется, потому что static действует на переменную-член только для того, чтобы указать, что сохранена копия, которая не изменится. Как понять эту копию? На самом деле статическая модификация загружается (инициализируется) при загрузке класса, и она будет загружена только один раз, то есть инициализирована один раз, так что никаких изменений не будет!

Что касается финальной модификации, она изменилась? Это переворачивает ваше мнение о финале? Блогер также подготовил статью об окончательном подробном объясненииПрограммист, ты действительно понимаешь последнее ключевое слово?

хорошо, статья здесь первая. Я надеюсь, что эта статья поможет вам понять статику. Если есть какие-либо недостатки или неточности, я надеюсь понять и приветствовать критику и исправления!

Если эта статья была вам хоть немного полезна, пожалуйста, поставьте лайк, спасибо~

Ссылаться на: "идеи программирования на Java"Baijiahao.Baidu.com/is?ID=160125… blog.CSDN.net/QQ_34337272… блог woo woo woo.cn на.com/dolphin0520…

Наконец, приглашаю всех обратить внимание на мою официальную учетную запись, обсудить технологии вместе, тосковать по технологиям и заниматься технологиями.

在这里插入图片描述