对象和封装
1.1面向对象设计
回顾面向对象
1.1.1、面向对象的好处
1.1.2、面向对象和面向过程的区别
优缺点比较
面向过程
优点:
流程化使得编程任务明确,在开发之前基本考虑了实现方式和最终结果,具体步骤清楚,便于节点分析。
效率高,面向过程强调代码的短小精悍,善于结合数据结构来开发高效率的程序。
缺点:
代码重用性低,扩展能力差,后期维护难度比较大。
面向对象
优点:
易维护、质量高、效率高、易拓展
缺点:
开销大,性能低
1.1.3、使用面向对象分析
- 第一步、分析需求,归纳出类
- 第二步、发现类的属性
- 第三步、发现类的方法
面向对象设计的过程就是抽象的过程。根据项目的需求,发现现实中的对象并抽象出软件中的对象,从而归纳出与项目所关联的类及类的属性和方法
- 为了更清楚的表示类,可以将设计结果通过类图进行描述
- 类图是软件工程的统一建模语言,是一种静态结构图
- 类图以反映类的结构(属性、操作)及类之间的关系为目的
- 示例如下
- 箭头指向的为父类
- +表示public
- -表示private
- #表示protected
1.1.4、设计类时遵循的原则如下
1、属性和方法时为了解决业务问题设置的。
2、关注主要属性和方法。
3、如果没有必要,那么不要增加额外的类,属性和方法
1.2、构造方法
-
new关键字创建对象然后赋值
AppleTree appletree =new AppleTree appletree.name="康康";
-
语法: [访问修饰符] 方法名 (参数列表){
// 方法体的代码
}
- 注意事项:
- 构造方法的名称和类名相同
- 没有返回值类型
- 构造方法的参数列表是可选的,可以定义无参构造和有参构造
- 一个类至少有一个无参构造,如果没有创建,系统会自动创建一个无参构造
示例
普通方法
public class Student {//Student类
//静态的特征(属性)
public String name;
public int age;
private String id;
//动态的特征(方法)
public void XieZuoYe(){
System.out.println(name+"正在写作业"+id);
}
public void XieZuoYe(String kemu){
System.out.println(name+"正在写"+kemu+"作业");
}
public void XieZuoYe(String kemu,int ShiJian){
System.out.println(name+"正在写"+kemu+"写了"+ShiJian+"小时");
}
}
public class Demo01 {//主方法
public static void main(String[] args) {
Student student=new Student();//构造无参构造函数
student.name="ikun";//给Student类的name赋值
student.XieZuoYe();//调用Student类里面第一个无参方法XieZuoYe
student.XieZuoYe("Java");//调用Student类里面只有一个参数的有参方法
student.XieZuoYe("Java",5);//调用Student类里面有两个参数的有参方法
}
}
构造方法
public class Student {
//静态的特征(属性)
public String name;
public int age;
private String id;
//动态的特征(方法)
public void XieZuoYe(){
System.out.println(name+"正在写作业"+id);
}
public void XieZuoYe(String kemu){
System.out.println(name+"正在写"+kemu+"作业");
}
public void XieZuoYe(String kemu,int ShiJian){
System.out.println(name+"正在写"+kemu+"写了"+ShiJian+"小时");
}
//构造方法
//构造方法和普通方法的区别 构造方法没有返回值 方法名和类名相同
//无参构造函数 系统默认
public Student(){};
//有参构造函数
public Student(String name,int age,String id){
this.name=name;
this.age=age;
this.id=id;
}
}
public class Demo01 {
public static void main(String[] args) {
Student student1=new Student("康康",5,"411224198703260513");//构造有参构造函数
student1.XieZuoYe();//调用Student类里边的无参方法XieZuoYe
student1.XieZuoYe("JAVA");//调用Student类里面有一个参数的有参方法
student1.XieZuoYe("JAVA",5);//调用Student类里面有两个参数的有参方法
}
}
注意:如果无参和有参同时出现,创建方法时会根据参数类型及数量自行对应 运行不同的构造方法
1.3 this关键字
1.3.1 使用this关键字调用成员变量解决成员变量与局部变量的同名冲突
public AppleTree(String name){
this.name=name;//成员变量和局部变量如果同名,必须使用this关键字
}
1.3.2 使用this关键字调用成员变量方法
public void changName(String name){
this.name=name;
this.print();//同一类中的某个方法
}
1.3.3 使用this关键字调用已定义的构造方法
以下代码中定义了Employee类,并定义了两个带参构造方法
public class Employee{
String name;
String sex;
int age;
String dept;
public Employee(String name,String sex){
this.name=name;
this.sex=sex;
}
public Employee(String name,Steing sex,int age,Strung dept){
this.name=name;
this.sex=sex;
this.age=age;
this.dept=dept;
}
}
从以上代码中可以看到this.name=name和this.sex=sex在两个构造方法中同时存在
在这种情况下我们就可以在一个构造方法中调用另一个构造方法
public class Employee{
String name;
String sex;
int age;
String dept;
public Employee(String naem,String sex){
this.name=name;
this.sex=sex;
}
pubilc Employee(String name,String sex,int age,String dept){
this(name,sex)//调用已定义的构造方法
this.age=age;
this.dept=dept;
}
}
这里使用this关键字调用构造方法,并传入局部变量name和sex作为参数。执行时,首先执行Employee(String name,String sex)构造方法,完成对name和sex属性的赋值;然后执行后面的语句实现对age属性和dept属性的赋值
需要注意的是,使用this关键字调用已定义的构造方法时,它只能用在构造方法中且必须作为构造方法的第一条语句
注意 this关键字实在对象内部代指自身的引用,所以this关键字只能调用实例变量、实例方法和构造方法,不能调用静态变量和静态方法,也不能调用局部变量
1.4 方法重载
1.4.1 方法重载的定义
方法重载指的是同一个类包含两个或两个以上的方法,它们的方法名相同,方法参数的个数或参数类型不同,成员变量和局部变量都可以进行重载 例如:
System.out.println("good"); System.out.println(true); System.out.println(100);
以上代码实现了对不同类型参数值的输出,这正是因为println()方法实现了对于不同参数类型的方法重载
1.4.2 方法重载的特点
- 在同一类中
- 方法名相同
- 参数列表不同
- 与返回值无关
注意 方法的返回值和方法的访问修饰符不能作为判断方法之间是否构成重载的依据
1.4.3 方法重载的使用和优点
实现的功能相同但是参数类型不同,可以考虑使用方法的重载
public class Test01 {
public static void main(String[] args) {
Demo01 demo01=new Demo01();
int a=6,b=8;
System.out.println(a+"+"+b+"="+demo01.gerSum(a,b));
double c=9.1,d=10.8;
System.out.println(c+"+"+d+"="+ demo01.getSum(c,d));
String e="Hello",f="World";
System.out.println(e+"+"+f+"="+demo01.getSum(e,f));
}
}
输出结果
6+8=14
9.1+10.8=19.9
Hello+World=HelloWorld
方法的重载可以根据参数的不同,采用不同的实现方法而且不需要编写多个名称,简化了类调用方法的代码
1.5 使用封装重构类的属性和方法
面向对象的三大特征之一:封装
将类的某些信息隐藏在类内部,不允许外部程序直接访问
而是通过该类提供的方法来实现对隐藏信息的操作和访问
封装的好处
- 隐藏类的实现细节
- 方便加入控制语句
- 方便修改实现
- 只能通过规定方法访问数据
1.5.1 封装的步骤
- 修改属性的可见性来限制对属性的访问
- 为每个属性创建一对赋值(setter)方法和取值(getter)方法,用于对这些属性的存取
- 在赋值方法中,可以加入对属性的取存控制语句
- 修改属性的可见性:将public修改为private
- 创建赋值和取值方法:属性被改为private后,其他类就无法访问了。如果想要访问它要为每个属性创建一对getter()方法和setter()方法,用于对这些属性的存取,其中setter()方法用来更新变量值,getter()方法用来读取变量值
public class Demo011 {
private String name="张三";//名字
private int age;//年龄
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Demo011() {
this.name="张三";
this.age=18;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age>=100||age<=0){
age=18;
}else{
this.age = age;
}
}
public Demo011(String name, int age) {
setAge(age);
this.name = name;
}
public void s(){
System.out.println(name+age);
}
}
public class Test011 {
public static void main(String[] args) {
Demo011 demo01111=new Demo011();
demo01111.s();
Demo011 demo011=new Demo011();
demo011.setName("王五");
demo011.setAge(19);
demo011.s();
Demo011 demo0111=new Demo011("赵六",55);
demo0111.s();
}
}
//输出结果
张三18
王五19
赵六55
面向对象的过程就是抽象的过程,他一共分为三步来完成 1、分析需求,归纳出类;2、发现类的属性;3、发现类的方法
1.5 类和类成员的访问控制
1.5.1 类的访问修饰符
修饰符 | 作用域 | |
同一包中 | 非同一包中 | |
public | 可以使用 | 可以使用 |
默认修饰符 | 可以使用 | 不可以使用 |
修饰符 | 作用域 | |||
同一类中 | 同一包中 | 子类中 | 外部包 | |
private | 可以使用 | 不可以使用 | 不可以使用 | 不可以使用 |
默认修饰符 | 可以使用 | 可以使用 | 不可以使用 | 不可以使用 |
protected | 可以使用 | 可以使用 | 可以使用 | 不可以使用 |
public | 可以使用 | 可以使用 | 可以使用 | 可以使用 |
访问修饰符的访问权限
- private:它具有最小的访问权限,仅仅能够在定义它的类中访问,具有类可见性。它是”封装“的体现,大多数属性的修饰符为private
- 默认修饰符:只能被同一个包中的类访问,具有包的可见性
- protected:可以被同一个包中的类访问,被同一个项目中不同包中的子类访问。
- public:它具有最大的访问权限,可以被所有类访问
1.5.3 static关键字
static关键字可以修饰类的属性、方法和代码块。使用static修饰的属性和方法不在属于具体的某个对象,而属于它所在的类
在Java中一般情况下调用类的成员需要先创建类的对象,然后通过对象进行调用。使用static可以直接用"."调用类的成员
1、用static关键字修饰属性和代码块
用static关键字修饰的变量属于这个类,因此由这个类创建的所有对象公用一个static变量。通常,用static关键字修饰的属性被称为静态变量或类变量,没有使用static关键字修饰的属性被称为实例变量
public class Demo03 {
public static int i;//静态变量
public static int age=19;//静态变量
public int height;//实例变量
static { //静态块
System.out.println("执行静态代码块");
i=15;
System.out.println("初始化i的值为:"+i);
System.out.println("初始化age的值为:"+age);
}
public Demo03() {
System.out.println("执行构造方法创造对象");
height=30;
System.out.println("初始化k的值为"+height);
}
}
public class Test03 {
public static void main(String[] args) {
Demo03 demo03=new Demo03();
System.out.println("main方法中修改变量的值");
demo03.height++;//引用实例变量
Demo03.i++;//引用静态变量
System.out.println("当前i的值为"+Demo03.i);
System.out.println("当前age的值为"+Demo03.age);
System.out.println("当前k的值为"+demo03.height);
}
}
输出结果
*******执行静态代码块
初始化i的值为:15
初始化age的值为:19
*******执行构造方法创造对象
初始化k的值为30
*******main方法中修改变量的值
当前i的值为16
当前age的值为19
当前k的值为31
注意 在方法里不可以定义static变量,也就是说,静态方法不能是局部变量
使用final关键字修饰的常量在整个程序运行时都不能被改变,和具体的对象没有关系,因此通常使用static关键字修饰,再类加载时执行一次,如通过"static final double PI=3.1415926"
- 常量名一般由大写字母组成
- 声明变量时一定要赋初值
1.5.4 用static关键字修饰方法
使用static关键字修饰的方法被称为静态方法或类方法,未使用static关键字修饰的方法被称为实例方法
public class Demo04 {
public static int i;
public static int j=10;
public int k;
public static void staticMethod(){
System.out.println("*********执行静态方法");
Demo04 demo04=new Demo04();//在静态方法中不能直接访问实例方法所以需要调用类的对象
demo04.k=25;
System.out.println("k的值为:"+demo04.k);
}
}
public class Test04 {
public static void main(String[] args) {
Demo04.staticMethod();
}
}
注意: 1、在静态方法中不能直接访问实例变量和实例方法
2、在实例方法中可以直接调用类中定义的静态变量和静态方法
静态方法的好处: 不用生成类的实例就可以直接调用,用类名直接"."调用即可
public static void main(String[] args) {
Demo04.staticMethod();//类名直接调用
}