站在C/C++的肩膀速通Java面向对象
默认学过C或C++,对变量、表达式、选择、循环都会。
运行特征
- 解释型语言(JavaScript、Python等)
源文件-(平台专属解释器)->解释器中执行 - 编译型语言(C++、Go等)
源文件-(平台编译器)->平台可执行文件 - Java
源文件-(通用编译器)->.class二进制文件-(平台JVM)->JVM中执行
Java名词解释
- JVM(Java Virtual Machine)虚拟机
- JRE(Java Runtime Environment)运行环境(包含JVM和解释器),有这个就能运行Java程序
- JDK(Java Development Kit)包含JRE和相关工具的Java开发环境
常用Dos命令
dir
查目录,不是ls
cd
进目录
d:
进D盘
mkdir
创建文件夹
rd
删除文件夹
cls
清屏
exit
退出
Java的相关文件(Windows平台)
.java文件
:Java源代码文件,包含了程序员编写的Java代码。.class文件
:Java字节码文件,是由Java编译器编译生成的中间代码文件,可以由Java虚拟机(JVM)执行。.jar文件
:JavaArchive文件,是一种归档文件格式,用于将多个Java类文件、资源文件和元数据打包成一个文件。通常用于分发和部署Java应用程序、库或组件。java.exe
:Java程序的执行器,用于执行已编译成的Java字节码文件(.class文件)。javac.exe
:Java编译器,用于编译Java源代码文件(.java文件)成为Java字节码文件(.class文件)。jar.exe
:Java归档工具,用于创建和管理Java归档文件(.jar文件),可以将多个.class文件打包成一个可执行的JAR文件。javadoc.exe
:Java文档生成工具,用于根据源代码中的注释生成API文档,将Java代码注释转换为HTML格式的文档。jdb.exe
:Java调试器,用于在调试Java程序时启动Java调试器,允许暂停程序、检查变量值、设置断点等操作。javap.exe
:Java反汇编器,用于反编译Java字节码文件(.class文件)成为Java源代码的形式,可以查看.class文件的内容,了解其中包含的类、方法、字段等信息。
一个Java程序开发通常如下:编写.java
源文件,使用javac.exe
编译成.class
文件,使用java.exe
执行.class
文件(不能带.class后缀,直接java 类名
)。
基本数据类型
- 整型(Integer Types):
- byte:8位,有符号,范围为 -128 到 127。
- short:16位,有符号,范围为 -32,768 到 32,767。
- int:32位,有符号,范围为 -2^31 到 2^31 - 1。
- long:64位,有符号,范围为 -2^63 到 2^63 - 1。
123L
- 浮点型(Floating-Point Types):
- float:32位,单精度浮点数,范围为大约 1.4e-45 到 3.4e+38,精确度为约 7 位小数。
12.2f
- double:64位,双精度浮点数,范围为大约 4.9e-324 到 1.8e+308,精确度为约 15 位小数。
- float:32位,单精度浮点数,范围为大约 1.4e-45 到 3.4e+38,精确度为约 7 位小数。
- 字符型(Character Type):
- char:16位,Unicode字符,范围为 ‘\u0000’(即 0)到 ‘\uffff’(即 65,535)。
- 布尔型(Boolean Type):
- boolean:表示 true 或 false 值。
易错:
引用数据类型
- 类(Class):类是用户定义的数据类型,用于创建对象。类包含属性(字段)和方法,可以通过实例化(创建对象)来访问它们。
- 接口(Interface):接口是一种抽象数据类型,用于定义类应该实现的方法。类可以实现一个或多个接口,以达到实现多态性和代码复用的目的。
- 数组(Array):数组是一组相同类型的数据元素的集合。数组在内存中是连续存储的,可以通过索引访问其中的元素。
- 枚举(Enum):枚举是一种特殊的类,用于定义一组命名的常量。枚举常量通常用于表示有限的一组可能值,如星期几、月份等。
- 字符串(String):字符串是Java中的特殊对象,用于表示文本数据。字符串是不可变的,可以进行各种操作,如连接、截取、替换等。
- 包装类(Wrapper Classes):包装类是一种将基本数据类型封装为对象的类。Java提供了一组包装类,如Integer、Double、Boolean等,用于在需要对象的上下文中使用基本数据类型。
- 自定义引用数据类型:除了以上提到的内置引用数据类型外,开发人员还可以创建自定义的引用数据类型,通过定义类和接口来实现自己的数据结构和算法。
控制台输入
import java.util.Scanner;class UseScanner {public static void main(String[] args) {Scanner input = new Scanner(System.in);System.out.println("Input your name: ");String name = input.next(); // 取字符串System.out.println("OK~ next... input your age: ");int age = input.nextInt(); // 取整数System.out.println("Hello " + name + ". And your age is " + age + ". Choose A or B please.");char a = input.next().charAt(0); // 取字符串第0个字System.out.println("You choose " + a);input.close();}
}
Java特别注意
- switch语句中允许接受
byte、short、int、char、String
作为变量,但不支持long
数组
class UseArray {public static void main(String[] args) {int[] arr; // 声明数组arr = new int[5]; // 分配空间int[] arr2 = { 1, 2, 3, 4, 5 }; // 声明,并(包含分配空间)赋值printArray(arr);System.out.println();printArray(arr2);}static void printArray(int[] arr) {for (int i = 0; i < arr.length; i++) {System.out.println(arr[i]);}}
}
class UseArray {public static void main(String[] args) {int[] arr = { 1, 2, 3 };// 拷贝扩容arr = Arrays.copyOf(arr, 10);printArray(arr);// 也能截取arr = Arrays.copyOf(arr, 2);printArray(arr);}static void printArray(int[] arr) {System.out.println(Arrays.toString(arr));}
}
import java.util.Arrays;class UseArray {public static void main(String[] args) {int[] arr = { 1, 2, 3 };printArray(arr);arr = extendArray(arr);printArray(arr);addArray(arr);printArray(arr);}static void printArray(int[] arr) {System.out.println(Arrays.toString(arr));}// 传入的是arr所指的地址static void addArray(int[] arr) {arr[0] = 10086;}static void extendArray(int[] arr) {arr = Arrays.copyOf(arr, 10);return arr;}}
可变长参数
只能放最后一个参数位置,作为数组形式使用。
class UseArray {public static void main(String[] args) {System.out.println(sumup("Hello", 1, 2, 3, 4, 5, 6, 7));}public static int sumup(String str, int... nums) {int sum = 0;System.out.println("Input String: " + str);for (int i = 0; i < nums.length; i++) {sum += nums[i];}return sum;}}
二维数组
class UseArray {public static void main(String[] args) {int[][] arrs1 = new int[3][5];arrs1[0][0] = 0;printArrays(arrs1);int[][] arrs2 = new int[3][];arrs2[0] = new int[5];arrs2[1] = new int[3];arrs2[2] = new int[1];printArrays(arrs2);int[][] arrs3 = { { 1, 2, 3 }, { 2, 3 }, { 3 } };printArrays(arrs3);return;}public static void printArrays(int[][] arrs) {for (int i = 0; i < arrs.length; i++) {for (int j = 0; j < arrs[i].length; j++)System.out.print(arrs[i][j] + " ");System.out.println();}System.err.println("--------------");return;}}
面向对象基础
public class Person {String name;int age;public void speak(String words) {System.out.println(name + "say: " + words);}public void jump() {System.out.println(name + "jumps to " + age);}
}
public class Test {public static void main(String[] args) {Person person = new Person();person.name = "小明";person.age = 18;person.speak("哈哈哈");person.jump();}
}
- 类由成员变量和方法组成
- 类中定义的变量是成员变量,实例化后存在堆空间中,创建后就有默认值,不会因为没有初始化成员变量而报错。
- 局部变量的优先级高于成员变量,在类方法中的同名局部变量会先于成员变量。如果在方法中需要使用成员变量,需要加上
this.
来访问。
方法重载
一个类中定义多个相同名称
的方法,但是参数列表不同
(类型、顺序、个数不同都算不同)。这与形参名、方法访问修饰符、返回值类型无关!
可以参考println()
函数的实现,有很多方法重载的例子。、
public void println(boolean x) {if (getClass() == PrintStream.class) {writeln(String.valueOf(x));} else {synchronized (this) {print(x);newLine();}}
}
public void println(char x) {if (getClass() == PrintStream.class) {writeln(String.valueOf(x));} else {synchronized (this) {print(x);newLine();}}
}
构造方法
类中的特殊方法,与类名同名。
没有返回值类型,只在创建对象时调用,无法通过方法调用。
没有在类中显式定义构造方法,由编译器提供无参构造方法。
构造方法也可以重载!在定义带参构造后需要补充无参构造!
public class Person {String name;int age;public Person() {System.out.println("Person created!");}public Person(String name) {this.name = name;}public void speak(String words) {System.out.println(name + "say: " + words);}public void jump() {System.out.println(name + "jumps to " + age);}
}
对象的创建步骤
this关键字
指向当前实例对象。实际是对象在虚拟机中的堆地址(在new的时候就已经确定)
- 在类方法中,可以避免与局部同名变量冲突。用于调用成员变量/方法。
- 构造方法内自调用
this()
public class Person {String name;int age;public Person() {System.out.println("Person created!");}public Person(String name) {this.name = name;}public Person(String name, int age) {this(name);this.age = age;}public void speak(String words) {System.out.println(name + "say: " + words);}public void jump() {System.out.println(name + "jumps to " + age);}
}
封装
隐藏必要的对象内部实现细节,控制对象属性、方法的使用与修改权限。
使用访问修饰符private
(私有,仅本类可见)。
属性的访问与修改使用getter和setter。
public class Person {String name;int age;private int score;public void setScore(int score) {if (score >= 0 && score <= 100)this.score = score;elsethis.score = 0;}public int getScore() {return this.score;}
}
继承
使用extends
关键字继承父类,实例化子类时,会先调用父类的构造方法,然后调用子类的构造方法。
默认会调用无参父类构造,如果需要调用带参构造,使用super(a,b,c...)
调用。
子类创建对象时并没有创建父类对象,只是在子类空间中创建了super指向的父类空间,所以只有一个子类对象实例。
public class Animal {private String name;int age;private double price;public Animal() {System.out.println("Animal Created!");}public Animal(String name) {System.out.println("Animal with name Created!");setName(name);}public Animal(String name, int age, double price) {this.name = name;this.age = age;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}}
public class Dog extends Animal {int age;public Dog() {super("MAKA");System.out.println("Dog created!");this.age = 233;super.age = 666;}public void speak() {System.out.println(getName() + " wang wang!");}}
public class Test {public static void main(String[] args) {Dog pt = new Dog();System.out.println(pt.age);pt.speak();return;}
}
// Animal with name Created!
// Dog created!
// 233
// MAKA wang wang!
属性的继承
父类的所有属性都可以被继承,但是私有属性不能被访问。
当子类和父类有同名属性时,通过super关键字区分,没标注this/super
优先访问this的。
public class Sup {int a;int b;}
public class Sub extends Sup {int b;public void speak() {System.out.println("a: " + a);System.out.println("this.b: " + this.b);System.out.println("super.b: " + super.b);}
}
public class Test {public static void main(String[] args) {Sub sub = new Sub();sub.a = 1;sub.b = 2;sub.speak();return;}
}// a: 1
// this.b: 2
// super.b: 0
方法的覆盖(重写)
当父类提供的方法无法满足子类需求时,对父类相同的方法(包括方法名和参数列表结构完全一致)覆盖。
子类覆盖的方法不能比父类的方法可见性小。父类私有的方法不会被重写(相当于不可见)。
子类返回值类型只能与父类一样或者是父类的子类和null,如果是基本数据类型,需要完全一致。
public class Sup {int a;int b;Sup speak() {return new Sub();}Sub speak(String words) {System.out.println("233");return new Sub();}}
public class Sub extends Sup {int b;Sub speak(String words) {super.speak(words);System.out.println("666");return new Sub();}
}
public class Test {public static void main(String[] args) {Sub sub = new Sub();sub.a = 1;sub.b = 2;sub.speak();sub.speak("");return;}
}
// 233
// 666
访问修饰符
多态
父类引用指向子类对象,产生了多态。(向上转型、里氏替换)
要求有继承关系,多态只能调用父类有的属性、方法,不能调用子类有的。
如果子类有父类方法的重写,则会调用子类的重写方法。
Pet pet = new Dog();
使用场景1:父类作为方法的形参实现多态,使得方法参数类型更宽泛(能用多个子类作为参数类型)
public class Animal {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public void eat() {System.out.println("Animal eat what?");}public void feed(Animal animal) {animal.eat(); // 实际上是调用子类的eat重写方法}}
public class Dog extends Animal {public void eat() {System.out.println("Dog eat something!");}
}
public class Cat extends Animal {public void eat() {System.out.println("Cat eat fish!");}
}
public class Test {public static void main(String[] args) {Animal dog = new Dog();dog.eat();Animal cat = new Cat();cat.eat();}
}
// Dog eat something!
// Cat eat fish!
使用场景2:父类作为方法的返回值实现多态,使得方法返回不同的子类对象(能用多个子类作为返回值)
public class Animal {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public void eat() {System.out.println("Animal eat what?");}public void feed(Animal animal) {animal.eat();}public Animal getAnimal(String type) {if (type.equals("Dog"))return new Dog();if (type.equals("Cat"))return new Cat();return null;}
}
public class Test {public static void main(String[] args) {Animal animal = new Animal();animal = animal.getAnimal("Cat");animal.eat();}
}
// Cat eat fish!
向下转型
父类无法调用子类的特有方法,需要强转(向下转型)后才能调用。要保证强转后的子类确实有这个方法。
public class Test {public static void main(String[] args) {Animal animal = new Cat();if (animal instanceof Cat) {Cat cat = (Cat) animal;cat.eatFish(); // Cat独有的方法}}
}
抽象类和抽象方法
https://www.bilibili.com/video/BV1994y1r7uV/?p=83&spm_id_from=pageDriver&vd_source=9cf1572a869a6a64c75ab4bdbe55f984
相关文章:

站在C/C++的肩膀速通Java面向对象
默认学过C或C,对变量、表达式、选择、循环都会。 运行特征 解释型语言(JavaScript、Python等) 源文件-(平台专属解释器)->解释器中执行编译型语言(C、Go等) 源文件-(平台编译器)->平台可执行文件Java 源文件-(…...

【AI视野·今日Robot 机器人论文速览 第七十八期】Wed, 17 Jan 2024
AI视野今日CS.Robotics 机器人学论文速览 Wed, 17 Jan 2024 Totally 49 papers 👉上期速览✈更多精彩请移步主页 Daily Robotics Papers Safe Mission-Level Path Planning for Exploration of Lunar Shadowed Regions by a Solar-Powered Rover Authors Olivier L…...

flask cors 跨域问题解决
座右铭:怎么简单怎么来,以实现功能为主。 欢迎大家关注公众号与我交流 环境安装 pip install -U flask-cors 示例代码 from flask import Flask from flask_cors import CORS, cross_originapp Flask(__name__) CORS(app, supports_credentialsTrue)…...

18 19 SPI接口的74HC595驱动数码管实验
1. 串行移位寄存器原理(以四个移位寄存器为例) 1. 通过移位寄存器实现串转并:一个数据输入端口可得到四位并行数据。 通过给data输送0101数据,那么在经过四个时钟周期后,与data相连的四个寄存器的输出端口得到了0101…...

计算机网络概述习题拾遗
学习目标: 自下而上第一个提供端到端服务的层次 路由器、交换机、集线器实现的功能层 TCP/IP体系结构的网络接口层对应OSI体系结构的哪两个层次 分组数量对总时延的影响 如果这篇文章对您有帮助,麻烦点赞关注支持一下动力猿吧! 学习内容…...

你的电脑关机吗
目录 程序员为什么不喜欢关电脑? 电脑长时间不关机会怎样? 电脑卡顿 中度风险 硬件损耗 能源浪费 散热问题 软件问题 网络安全问题 程序员为什么不喜欢关电脑? 大部分人都会选择将电脑进行关机操作。其实这不难理解,毕竟人类都需要…...

flask+python儿童福利院管理系统pycharm毕业设计项目
本系统解决了儿童福利院管理事务中的主要问题,包括首页、个人中心、爱心人士管理、员工管理、后勤人员管理、儿童信息管理、院所风采管理、活动管理、食谱管理、领养流程管理、政策法规管理、楼栋管理、宿舍管理、领养申请管理、义工申请管理、捐赠信息管理、宿舍物…...
React:高阶组件|ref转发
高阶组件 参考文档:高阶组件 – React (reactjs.org) 高阶组件(Higher-Order Components,简称 HOC)是React中用于复用组件逻辑的一种高级技巧。具体而言:高阶组件是参数为组件,返回值为新组件的函数。 组件…...

AI:127-基于卷积神经网络的交通拥堵预测
🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的关键代码,详细讲解供…...
MongoDB聚合操作符:$abs
$abs聚合操作符用于返回数值的绝对值。 语法 { $abs: <数值> }<数值>表达式可以是任何能被解析为数值的合法表达式。 用法 如果$abs的<number>参数被解析为null值或引用不存在的字段,将返回null,如果参数被解析为NaN,也…...
【element-ui】输入框组件el-input输入数字/输出Number类型:type=“number“、v-model.number用法
输入框组件el-input输入数字/输出Number类型 1、基础用法 输入:任何文本 → 输出:String类型 <el-input v-model"inputText"></el-input> <!-- 输入 abc —— inputText输出 "abc" 输入 123 —— inputText输出 …...

算法与数据结构
算法与数据结构 前言 什么是算法和数据结构? 你可能会在一些教材上看到这句话: 程序 算法 数据结构 算法(Algorithm):是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代…...

C++动态规划-线性dp算法
莫愁千里路 自有到来风 CSDN 请求进入专栏 X 是否进入《C专栏》? 确定 目录 线性dp简介 斐波那契数列模型 第N个泰波那契数 思路: 代码测试: 三步问题 思路: 代码测试: 最小花费爬楼梯 思路…...

基于 Python 深度学习的电影评论情感分析系统,附源码
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...

如何查看Apple Watch的步数?这里提供几个方法
所有Apple Watch都配有内置计步器,即具有步进跟踪功能。当你第一次设置手表时,你的Apple Watch将自动开始计算步数。让我们看看如何在Apple Watch上查看步数。 使用活动应用程序 1、按下Apple Watch上的数字皇冠,打开应用程序屏幕。 2、点击活动应用程序。 3、你会看到…...

解决‘vue‘ 不是内部或外部命令,也不是可运行的程序(设置全局变量)
发现是没有执行: npm install -g vue/cli 但是发现还是不行 此时,我们安装了 Vue CLI,但是在运行 vue ui 命令时出现了问题。这通常是因为全局安装的 Vue CLI 的路径没有被正确地添加到系统的环境变量中。 可以尝试以下几种方法来解决这个问…...

JavaWeb学习|i18n
学习材料声明 所有知识点都来自互联网,进行总结和梳理,侵权必删。 引用来源:尚硅谷最新版JavaWeb全套教程,java web零基础入门完整版 i18n 国际化(Internationalization)指的是同一个网站可以支持多种不同的语言&…...
数据库日志已经很大了,比如200多G,不能收缩到几兆,实际操作过只能到30G
当数据库日志文件(通常称为事务日志或事务日志文件)变得非常大时,确实可能会遇到问题,因为这会占用大量的磁盘空间,并可能影响数据库的性能。收缩日志文件到非常小的大小(例如从200多G到几兆)可…...

docker常用容器命令
首先说下容器: 它是指当docker运行镜像时,创建了一个隔离环境,称之为 容器。 这种方式优点:可以开启多个服务,服务之前是互相隔离的(比如:在一台服务器上可以开启多个mysql,可以是…...
蓝桥杯(Web大学组)2022省赛真题:冬奥大抽奖
思路: 使用模板字符串,借助time的值选择添加或移除样式的盒子,由于盒子的类名最多为li9,所以要将time的值取余,且判断余数为0时,就取1,否则会获取空值报错 .ul .li${time%9!0?time%9:1} 代码…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...