热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java面向对象编程核心概念解析与应用

本文深入解析了Java面向对象编程的核心概念及其应用,重点探讨了面向对象的三大特性:封装、继承和多态。封装确保了数据的安全性和代码的可维护性;继承支持代码的重用和扩展;多态则增强了程序的灵活性和可扩展性。通过具体示例,文章详细阐述了这些特性在实际开发中的应用和优势。
面向对象的特征

三大特征

package com.cloud.day2;

/*

面向对象三大特征:

   1. 封装

   2. 继承

   3  多态。

需求:  使用java类描述百合网的会员。

问题:性别有问题??


根本原因:由于其他人可以直接操作sex属性。可以对sex属性进行了直接的赋值。


封装:

权限修饰符:权限修饰符就是控制变量可见范围的。


public :  公共的。 public修饰的成员变量或者方法任何人都可以直接访问。

private 私有的, private修饰的成员变量或者方法只能在本类中进行直接访问。

封装的步骤:

   1. 使用private修饰需要被封装的属性。

   2. 提供一个公共的方法设置或者获取该私有的成员属性。

         命名规范:

           set属性名();

           get属性名();

 

疑问:封装一定要提供get或者set方法吗?

      不一定,根据需求而定的。

 

规范在现实开发中一般实体类的所有成员属性(成员变量)都要封装起来。

 

实体类:实体类就是用于描述一类事物的就称作为实体类。

工具类(Arrays数组的工具类):

 

封装的好处:

   1. 提高数据的安全性。

   2. 操作简单。

   3. 隐藏了实现。

*/

class Member{

   public String name;

   private String sex;

   public int salary;

   public void setSex(String s){

      if(s.equals("")||s.equals("")){

        sex = s;

      }

      else{

        sex = "";

      }

   }

   public String getSex(){

      return sex;

   }

   public void talk(){

      System.out.println("comunicate very happy....");

   }

}

public class Demo5 {

   public static void main(String[] args) {

      Member m = new Member();

      m.name = "Spring";

      m.setSex("");

      m.salary = 8888;

      System.out.println(m.name+";"+m.getSex()+";"+m.salary+";");

   }

}

计算案例

package com.cloud.day2;

 

/*

需求:使用java类描述一个计算器类,计算器具备操作数1操作数2 、操作符三个公共的属性

,还具备计算的功能行为。

要求:不能直接对操作数1,操作数2,运算符这些属性进行直接的赋值,要封装起来。 (+ - * /  )

根据需求提供get或者set方法。

   需要提供set方法

*/

class Calculator{

   private int num1;

   private int num2;

   private char option;

   public void initCalculator(int n1 , int n2 , char o){

      num1 = n1 ;

      num2 = n2 ;

      if(o==‘+‘||o==‘-‘||o==‘*‘||o==‘/‘){

        option = o;

      }else{

        option = ‘+‘;

      }

   }

   public void calculator(){

      switch (option) {

      case ‘+‘:

        System.out.println(num1+num2);

        break;

      case ‘-‘:

        System.out.println(num1-num2);

        break;

      case ‘*‘:

        System.out.println(num1*num2);

        break;

      case ‘/‘:

        System.out.println(num1/num2);

        break;

      }

   }

}

public class Demo6 {

   public static void main(String[] args) {

      Calculator c = new Calculator();

      c.initCalculator(1, 2, ‘+‘);

      c.calculator();

   }

}

操作数组

package com.cloud.day2;

import java.util.Arrays;

/*

需求:目前存在数组:int[] arr = {0,0,12,1,0,4,6,0} ,编写一个函数

接收该数组,然后把该数组的0清空,然后返回一个不存在0元素的数组。

 

步骤:

   1. 计算机新数组的长度。  原来的数组长度-0的个数

*/

public class Demo7 {

   public static void main(String[] args) {

      int[] arr = {0,1,2,3,0,4};

      arr = cleanZera(arr);

      System.out.println(Arrays.toString(arr));

   }

   public static int[] cleanZera(int []arr){

      int count = 0;

      for(int i=0;ilength;i++){

        if(arr[i]==0){

           count++;

        }

      }

      int index = 0;

      int[] newArr = new int[arr.length-count];

      for(int i=0;ilength;i++){

        if(arr[i]!=0){

           newArr[index]=arr[i];

           index++;

        }

      }

      return newArr;

   }

}

构造函数

package com.cloud.day3;

/*

java面向对象的语言: "万物皆对象": 任何事物都可以使用类进行描述。

需求:使用java类描述一个婴儿.

在现实生活中有两种婴儿,一种婴儿一出生就具备了名字(白户),还有一种婴儿就是出生之后才有名字(黑户)

 

构造函数:

构造函数的作用:给对应的对象进行初始化。

构造函数的定义的格式:

   修饰符  函数名(形式参数){

      函数体...

   }

构造函数要注意的细节:

   1. 构造函数是没有返回值类型的。

   2. 构造函数的函数名必须要与类名一致。

   3. 构造函数并不是由我们手动调用的,而是在创建对应的对象时,jvm就会主动调用到对应的构造函数。

   4. 如果一个类没有显式的写上一个构造方法时,那么java编译器会为该类添加一个无参的构造函数的。

   5. 如果一个类已经显式的写上一个构造方法时,那么java编译器则不会再为该类添加一个无参的构造方法。

   6. 构造函数是可以在一个类中以函数重载的形式存在多个的。 

疑问:创建对象时,jvm就会调用到对应的构造方法,那么我们以前没有学构造方法,那么

以前创建对象时,jvm是否也会调用构造方法呢?如果有?构造方法从何而来呢?


        会调用, java编译器在编译的时候给加上去的。


jdk提供了一个java开发工具(javap.exe)给我们进行反编译的。

javap反编译工具的使用格式:

      javap -c -l -private 类名

疑问: java编译器添加的无参构造方法的权限修饰符是什么?

      与类的权限修饰是一致的。

构造函数与普通函数的区别:

   1. 返回值类型的区别:

      1. 构造函数是没有返回值类型的,

      2. 普通函数是有返回值类型的,即使函数没有返回值,返回值类型也要写上void

   2. 函数名的区别:

      1. 构造函数的函数名必须要与类名一致,

      2. 普通函数的函数名只要符合标识符的命名规则即可。

   3. 调用方式的区别:

      1. 构造函数是在创建对象的时候由jvm调用的。

      2. 普通函数是由我们使用对象调用的,一个对象可以对象多次普通的函数,

   4. 作用上的区别:

      1. 构造函数的作用用于初始化一个对象。

      2. 普通函数是用于描述一类事物的公共行为的。

*/

class Baby{

   int id;

   String name;

   public Baby(int i , String n){

      id = i;

      name = n;

      System.out.println("属性初始化完毕...");

   }

   public Baby(){}

   public void cry(){

      System.out.println("Baby哭了...");

   }

}

public class Demo2 {

   public static void main(String[] args) {

      Baby b1 = new Baby(1,"summer");

      System.out.println(b1.id+";"+b1.name);

      b1.cry();

      b1.cry();

   }

}

构造函数案例

package com.cloud.day3;

/*

描述一个员工类,员工具备的属性:id\ name \ age

具备的公共行为:工作。

要求:一旦创建一个员工对象的时候,那么该员工对象就要对应的属性值。

*/

class Employee{

   int id;

   String name;

   int age;

   public Employee(int i,String n,int a){

      id = i;

      name = n;

      age = a;

   }

   public void work(){

      System.out.println(name+"好好工作");

   }

}

public class Demo3 {

   public static void main(String[] args) {

      Employee emp = new Employee(1, "ss", 12);

      System.out.println(emp.id+emp.name+emp.age);

   }

}

构造代码块

package com.cloud.day3;

/*

构造代码块:


构造代码块的作用:给对象进行统一的初始化。


构造函数的作用:给对应的对象进行初始化。

构造代码块的格式:

  

   {

      构造代码块

   }


注意:构造代码块的大括号必须位于成员位置上。

代码块的类别:

   1. 构造代码块。

   2. 局部代码块.   大括号位于方法之内。  作用:缩短局部变量的生命周期,节省一点点内存。

   3. 静态代码块  static

*/

class Body{

   int id;

   String name;

   {

      System.out.println("构造代码块....");

   }

   public Body(int i,String n){

      id = i;

      name = n;

   }

   public Body(){}

   public void talk(){

      System.out.println(name+":speak...");

   }

}

public class Demo4 {

   public static void main(String[] args) {

      Body b1 = new Body(1,"summer");

      b1.talk();

   }

}

 

注意事项

package com.cloud.day3;

/*

构造代码块要注意的事项:

   1. java编译器编译一个java源文件的时候,会把成员变量的声明语句提前至一个类的最前端。

   2. 成员变量的初始化工作其实都在在构造函数中执行的。

   3. 一旦经过java编译器编译后,那么构造代码块的代码块就会被移动构造函数中执行,是在构造函数之前执行的,构造函数的中代码是最后执行的。

   4. 成员变量的显示初始化与构造代码块的代码是按照当前代码的顺序执行的。

*/

public class Demo5 {

   public Demo5(){

      i=30000;

   }

   //代码块初始化

   {

      i=20000;

   }

   int i = 20000; //成员变量最先初始化

   public static void main(String[] args) {

      Demo5 d = new Demo5();

      System.out.println("i="+d.i);

   }

}

This关键字

package com.cloud.day3;

/*

需求:使用java类描述一个动物。

问题:存在同名的成员变量与局部变量时,在方法的内部访问的是局部变量(java 采取的是就近原则的机制访问的。)


this关键字:

this关键字代表了所属函数的调用者对象。

this关键字作用:

   1. 如果存在同名成员变量与局部变量时,在方法内部默认是访问局部变量的数据,可以通过this关键字指定访问成员变量的数据。

   2. 在一个构造函数中可以调用另外一个构造函数初始化对象。

this关键字调用其他的构造函数要注意的事项:

   1. this关键字调用其他的构造函数时,this关键字必须要位于构造函数中的第一个语句。

   2. this关键字在构造函数中不能出现相互调用的情况,因为是一个死循环。

this关键字要注意事项:

   1. 存在同名的成员变量与局部变量时,在方法的内部访问的是局部变量(java 采取的是就近原则的机制访问的。)

   2. 如果在一个方法中访问了一个变量,该变量只存在成员变量的情况下,那么java编译器会在该变量的前面添加this关键字。

*/

class Animal{

   String name;

   String color;

   public Animal(String n,String c){

      this.name = n;

      this.color = c;

   }

   public void eat(){

      System.out.println("this:"+this);

      String name = "sum";

      System.out.println(name+"...");

   }

}

public class Demo6 {

   public static void main(String[] args) {

      Animal dog = new Animal("dog","bai");

      Animal cat = new Animal("cat","black");

      cat.eat();

   }

}

注意事项

package com.cloud.day3;

/*

this关键字调用其他的构造函数要注意的事项:

   1. this关键字调用其他的构造函数时,this关键字必须要位于构造函数中的第一个语句。

   2. this关键字在构造函数中不能出现相互调用的情况,因为是一个死循环。

*/

class Student{

   int id;

   String name;

   public Student(int id,String name){

      this(name);

      this.id = id;

      System.out.println("两个参数的构造方法被调用了");

   }

   public Student(){

      System.out.println("调用了无参的构造方法...");

   }

   public Student(String name){

      this.name = name;

      System.out.println("一个参数的构造方法被调用了...");

   }

}

public class Demo7 {

   public static void main(String[] args) {

      Student s1 = new Student(12,"Sum");

      System.out.println(s1.id+";"+s1.name);

      Student s2 = new Student("Spring");

      System.out.println(s2.name);

   }

}

构造方法中的this

package com.cloud.day3;

/*

需求:使用java定义一个人类,人具备 idname age三个属性,还具备一个比较年龄的方法。

要求:必须写上构造函数,构造函数也必须要使用上this关键字。

*/

class Person{

   int id;

   String name;

   int age;

   public Person(int id,String name,int age){

      this.id = id;

      this.name = name;

      this.age = age;

   }

   public void compareAge(Person p2){

      if(this.age>p2.age){

        System.out.println(this.name+"年龄大");

      }else if(this.ageage){

        System.out.println(p2.name+"年龄大");

      }else{

        System.out.println("一样大");

      }

   }

}

public class Demo8 {

   public static void main(String[] args) {

      Person p1 = new Person(110,"nihao",17);

      Person p2 = new Person(111,"haha",12);

      p1.compareAge(p2);

   }

}

Static关键字

package com.cloud.day3;

/*

static(静态)

需求:描述一下学生类。  都是中国人....

目前存在的问题:所有的学生都是中国的,有n个学生就会有n份中国的数据存内存中,这样子

会浪费内存。

目前方案:中国这个数据移动到数据共享区中,共享这个数据给所有的Student对象使用即可。

 

问题2如何才能把这个数据移动到数据共享区中共享呢?

解决方案:只需要使用static修饰该数据即可。

静态的成员变量只会在数据共享区中维护一份,而非静态成员变量的数据会在每个对象中都维护一份的。。

*/

class Student1{

   String name;

   //使用了static修饰country,那么这时候country就是一个共享的数据。

   static String county = "China";

   public Student1(String name){

      this.name = name;

   }

}

public class Demo9 {

   public static void main(String[] args) {

      Student1 s1 = new Student1("Sum");

      Student1 s2 = new Student1("Aut");

      System.out.println(s1.name+";"+s1.county);

      System.out.println(s2.name+";"+s2.county);

      //因为county是共享的数据,这里修改了

      s2.county = "Anhui";

      System.out.println(s1.name+";"+s1.county);

      System.out.println(s2.name+";"+s2.county);

   }

}

Static修饰成员变量

package com.cloud.day3;

/*

static(静态\修饰符)

   1. static修饰成员变量:如果有数据需要被共享给所有对象使用时,那么就可以使用static修饰。

      静态成员变量的访问方式:

           方式1可以使用对象进行访问。

              格式:对象.变量名。


           方式二:可以使用类名进行访问。

              格式:类名.变量名;

        注意:

           1. 非静态的成员变量只能使用对象进行访问,不能使用类名进行访问。

           2. 千万不要为了方便访问数据而使用static修饰成员变量,只有成员变量的数据是真正需要被共享的时候

           才使用static修饰。


      static修饰成员变量的应用场景:如果一个数据需要被所有对象共享使用的时候,这时候即可好实用static修饰。

   2. static修饰成员函数:

*/

public class Demo10 {

   static String name;//非静态成员变量

   static String color = "white";//静态成员变量

   public static void main(String[] args) {

     

   }

}

Static统计案例

package com.cloud.day3;

/*

需求:统计一个类被使用了多少次创建对象,该类对外显示被创建的次数。

*/

class CountUse{

   static int count = 0;

   String name;

   {

      count++;

   }

   public CountUse(String name){

      this.name = name;

   }

   public CountUse(){}

   public int showCount(){

      return count;

   }

}

public class Demo11 {

   public static void main(String[] args) {

      CountUse cu1 = new CountUse();

      CountUse cu2 = new CountUse();

      CountUse cu3 = new CountUse();

      System.out.println(cu3.showCount());

   }

}

静态函数

package com.cloud.day4;

/*

静态函数:

static(静态、修饰符)

   static修饰成员变量时:static修饰成员变量时,那么该成员变量的数据就是一个共享的数据.

      静态成员变量的访问方式:

           方式一:使用对象进行访问。

                 对象.属性名

           方式二:可以使用类名进行访问。

                 类名.属性名

      注意:

        1. 非静态成员变量不能类名直接访问,只能使用对象进行访问。

        2. 千万不要为了方便访问成员变量而使用static修饰,一定要是该数据是共享数据时才使用static修饰。

 

   static修饰方法(静态的成员方法):

      访问方式:

        方式一:可以使用对象进行访问。

              对象.静态的函数名();

        方式二:可以使用类名进行访问。

              类名.静态函数名字。

      推荐使用是类名直接访问静态的成员。

 

静态的成员变量与非静态的成员变量的区别:

   1. 作用上的区别:

      1. 静态的成员变量的作用共享一个数据给所有的对象使用。

      2. 非静态的成员变量的作用是描述一类事物的公共属性。

   2. 数量与存储位置上的区别:

      1. 静态成员变量是存储方法区内存中,而且只会存在一份数据。

      2. 非静态的成员变量是存储在堆内存中,有n个对象就有n份数据。

   3. 生命周期的区别:

      1. 静态的成员变量数据是随着类的加载而存在,随着类文件的消失而消失。

      2.非静态的成员数据是随着对象的创建而存在,随着对象被垃圾回收器回收而消失。

 

静态函数要注意的事项:

   1. 静态函数是可以调用类名或者对象进行调用的,而非静态函数只能使用对象进行调用。

   2. 静态的函数可以直接访问静态的成员,但是不能直接访问非静态的成员。  

      原因:静态函数是可以使用类名直接调用的,这时候可能还没有存在对象,

      而非静态的成员数据是随着对象的存在而存在的。

 

   3. 非静态的函数是可以直接访问静态与非静态的成员。

      原因:非静态函数只能由对象调用,当对象存在的时候,静态数据老早就已经存在了,而非静态

      数据也随着对象的创建而存在了。

 

   4. 静态函数不能出现this或者super关键字。

      原因:因为静态的函数是可以使用类名调用的,一旦使用类名调用这时候不存在对象,而this

      关键字是代表了一个函数的调用者对象,这时候产生了冲突。

 

静态的数据的生命周期:静态的成员变量数据是优先于对象存在的。

static什么时候修饰一个函数?

   如果一个函数没有直接访问到非静态的成员时,那么就可以使用static修饰了。一般用于工具类型的方法

  

静态函数不能访问非静态的成员?

    静态函数只要存在有对象,那么也可以访问非静态的数据。只是不能直接访问而已。

*/

class Student{

   String name;

   static String county = "中国";

   //静态代码块:静态代码块是在Student.class文件加载到内存的时候就马上执行的。

   static {

      System.out.println("静态代码块执行了...");

   }

   public Student(String name){

      this.name = name;

   }

   public void study(){

      System.out.println("好好学习..."+this);

   }

   //静态方法与非静态方法的字节码文件是同时存在内存中的。只是静态的成员变量数据是优先于对象存在而已。

   public static void sleep(){

      Student s1 = new Student("sum");

      System.out.println(s1.name+"睡觉了...");

   }

}

public class Demo1 {

   public static void main(String[] args) {

      Student.sleep();

   }

}

Java面向对象常见概念


推荐阅读
  • 提升Android开发效率:Clean Code的最佳实践与应用
    在Android开发中,提高代码质量和开发效率是至关重要的。本文介绍了如何通过Clean Code的最佳实践来优化Android应用的开发流程。以SQLite数据库操作为例,详细探讨了如何编写高效、可维护的SQL查询语句,并将其结果封装为Java对象。通过遵循这些最佳实践,开发者可以显著提升代码的可读性和可维护性,从而加快开发速度并减少错误。 ... [详细]
  • 在Android应用开发中,实现与MySQL数据库的连接是一项重要的技术任务。本文详细介绍了Android连接MySQL数据库的操作流程和技术要点。首先,Android平台提供了SQLiteOpenHelper类作为数据库辅助工具,用于创建或打开数据库。开发者可以通过继承并扩展该类,实现对数据库的初始化和版本管理。此外,文章还探讨了使用第三方库如Retrofit或Volley进行网络请求,以及如何通过JSON格式交换数据,确保与MySQL服务器的高效通信。 ... [详细]
  • 本文详细介绍了使用 Python 进行 MySQL 和 Redis 数据库操作的实战技巧。首先,针对 MySQL 数据库,通过 `pymysql` 模块展示了如何连接和操作数据库,包括建立连接、执行查询和更新等常见操作。接着,文章深入探讨了 Redis 的基本命令和高级功能,如键值存储、列表操作和事务处理。此外,还提供了多个实际案例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • 本文探讨了资源访问的学习路径与方法,旨在帮助学习者更高效地获取和利用各类资源。通过分析不同资源的特点和应用场景,提出了多种实用的学习策略和技术手段,为学习者提供了系统的指导和建议。 ... [详细]
  • SQLite数据库CRUD操作实例分析与应用
    本文通过分析和实例演示了SQLite数据库中的CRUD(创建、读取、更新和删除)操作,详细介绍了如何在Java环境中使用Person实体类进行数据库操作。文章首先阐述了SQLite数据库的基本概念及其在移动应用开发中的重要性,然后通过具体的代码示例,逐步展示了如何实现对Person实体类的增删改查功能。此外,还讨论了常见错误及其解决方法,为开发者提供了实用的参考和指导。 ... [详细]
  • HBase Java API 进阶:过滤器详解与应用实例
    本文详细探讨了HBase 1.2.6版本中Java API的高级应用,重点介绍了过滤器的使用方法和实际案例。首先,文章对几种常见的HBase过滤器进行了概述,包括列前缀过滤器(ColumnPrefixFilter)和时间戳过滤器(TimestampsFilter)。此外,还详细讲解了分页过滤器(PageFilter)的实现原理及其在大数据查询中的应用场景。通过具体的代码示例,读者可以更好地理解和掌握这些过滤器的使用技巧,从而提高数据处理的效率和灵活性。 ... [详细]
  • 在本节课程中,我们将深入探讨 JSP 编程中的实际案例,通过具体代码示例 `code316.java` 来解析数据库连接的实现。该示例展示了如何使用 Java 的 JDBC API 进行数据库操作,包括加载数据库驱动、建立连接等关键步骤。通过本课程的学习,读者将能够更好地理解和应用 JSP 中的数据库连接技术。 ... [详细]
  • 在Java编程中,`AbstractClassTest.java` 文件详细解析了抽象类的使用方法。该文件通过导入 `java.util.*` 包中的 `Date` 和 `GregorianCalendar` 类,展示了如何在主方法 `main` 中实例化和操作抽象类。此外,还介绍了抽象类的基本概念及其在实际开发中的应用场景,帮助开发者更好地理解和运用抽象类的特性。 ... [详细]
  • 在探讨Hibernate框架的高级特性时,缓存机制和懒加载策略是提升数据操作效率的关键要素。缓存策略能够显著减少数据库访问次数,从而提高应用性能,特别是在处理频繁访问的数据时。Hibernate提供了多层次的缓存支持,包括一级缓存和二级缓存,以满足不同场景下的需求。懒加载策略则通过按需加载关联对象,进一步优化了资源利用和响应时间。本文将深入分析这些机制的实现原理及其最佳实践。 ... [详细]
  • Android中将独立SO库封装进JAR包并实现SO库的加载与调用
    在Android开发中,将独立的SO库封装进JAR包并实现其加载与调用是一个常见的需求。本文详细介绍了如何将SO库嵌入到JAR包中,并确保在外部应用调用该JAR包时能够正确加载和使用这些SO库。通过这种方式,开发者可以更方便地管理和分发包含原生代码的库文件,提高开发效率和代码复用性。文章还探讨了常见的问题及其解决方案,帮助开发者避免在实际应用中遇到的坑。 ... [详细]
  • 在使用SSH框架进行项目开发时,经常会遇到一些常见的问题。例如,在Spring配置文件中配置AOP事务声明后,进行单元测试时可能会出现“No Hibernate Session bound to thread”的错误。本文将详细探讨这一问题的原因,并提供有效的解决方案,帮助开发者顺利解决此类问题。 ... [详细]
  • 本文详细介绍了如何在Java Web服务器上部署音视频服务,并提供了完整的验证流程。以AnyChat为例,这是一款跨平台的音视频解决方案,广泛应用于需要实时音视频交互的项目中。通过具体的部署步骤和测试方法,确保了音视频服务的稳定性和可靠性。 ... [详细]
  • Jeecg开源社区正式启动第12届架构技术培训班,现已开放报名。本次培训采用师徒制模式,深入探讨Java架构技术。类似于大学导师指导研究生的方式,特别适合在职人员。导师将为学员布置课题,提供丰富的视频资料,并进行一对一指导,帮助学员高效学习和完成任务。我们的教学方法注重实践与理论结合,旨在培养学员的综合技术能力。 ... [详细]
  • 动态壁纸 LiveWallPaper:让您的桌面栩栩如生(第二篇)
    在本文中,我们将继续探讨如何开发动态壁纸 LiveWallPaper,使您的桌面更加生动有趣。作为 2010 年 Google 暑期大学生博客分享大赛 Android 篇的一部分,我们将详细介绍 Ed Burnette 的《Hello, Android》第三版中的相关内容,并分享一些实用的开发技巧和经验。通过本篇文章,您将了解到如何利用 Android SDK 创建引人入胜的动态壁纸,提升用户体验。 ... [详细]
  • 在Ubuntu系统中配置Python环境变量是确保项目顺利运行的关键步骤。本文介绍了如何将Windows上的Django项目迁移到Ubuntu,并解决因虚拟环境导致的模块缺失问题。通过详细的操作指南,帮助读者正确配置虚拟环境,确保所有第三方库都能被正确识别和使用。此外,还提供了一些实用的技巧,如如何检查环境变量配置是否正确,以及如何在多个虚拟环境之间切换。 ... [详细]
author-avatar
众大文化_724
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有