1.开发中如何建包
包的作用
-
1、把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
-
2、如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
-
3、包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。
一.先在src下面建立包
这个包也叫做根包
根包命名
cn :代表中国
qq :代表公司的英文
xiangmu :代表项目名
二:在根包的基础上建立子包
写代码不直接写在根包上,而是写在子包上
那么子包如何命名呢?
entity:存放实体(老师类,学生类等等)
until:存放工具
web:存放控制层
service:存放业务
dao:存放数据库
狗和企鹅的基础用例
+:本质就是公有的意思,用于不在一个包的变量的调用。
包的使用
包可以通过插入(import)进行使用其他包内的类,但是注意如果调用别的包里的类名字和你自己包里面类名字一样的话,必须要详细的类,即包名加类名
导入方法:import.类 或者import.*(代表自动导入)
在Java中,为了装载使用已编译好的包,通常可使用以下三种方法: (1) 在要引用的类名前带上包名作为修饰符。如: Animals.Cat cat=new Animals.Cat(); 其中Animals是包名,Cat是包中的类,cat是类的对象。 (2)在文件开头使用import引用包中的类。如: import Animals.Cat;
(3)在文件前使用import引用整个包。如:
import Animals.*;
package cn.qq.xiangmu.entity;//包名 public class Dog{ public String name;//这里因为要在测试包里面调用这个变量,因为不在一个包里面,所以要把变量变成共有的 public int health; public int love; public String strain; public void show(){ System.out.println("宠物的自白:"); System.out.println("我的名字是:"+name+",我的健康值是:"+health+",我和主人的亲密度是:"+love+",我是一值"+strain); } }
package cn.qq.xiangmu.entity;//包名 public class penguin { public String name; public int health; public int love; public String sex; public void show(){ System.out.println("宠物的自白:"); System.out.print("我的名字是:"+name+",我的健康值是:"+health+",我和主人的亲密度是:"+love+",我性别是"+sex); } }
package cn.qq.xiangmu.test; import cn.qq.xiangmu.entity.Dog;//因为Dog与test不在一个包里面,所以要引用进来,相当于介绍一下这个包 import cn.qq.xiangmu.entity.penguin; /* import cn.qq.xiangmu.entity.* 这个意思是直接引用entity包下面的类,不用一个一个写 */ public class Demo01{ public static void main(String[] args) { Dog dog=new Dog(); penguin penguin=new penguin(); //dog.name注意这里不能访问,因为不是在一个包下面,所以要把变量变成共有的,如果是在一个包下面,那么不用把变量变成公有的 dog.name="欧欧"; dog.health=100; dog.love=0; dog.strain="德国牧羊犬"; dog.show(); penguin.name="美美"; penguin.health=90; penguin.love=10; penguin.sex="Q妹"; penguin.show(); } }
无参和满惨构造函数
任何一个类都默认有一个构造函数,这个构造函数没有返回值,没有参数,也没有内容,且是共有的(public)
package cn.qq.xiangmu.entity;//包名 /* 构造函数特征 1.没有返回值 2.跟类名保持一致 有返回值的是方法: 方法函数格式: 权限修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2…) { 方法体; return 返回值; public Dog{ } 在主函数里面new Dog()的时候就是底层调用这个构造函数,这个构造函数可以不用写,都会默认有这个构造函数,所以一个类 ,你不写构造函数,是默认有一个无参的公有的,且里面没有内容的构造函数 如果自定义了一个有参构造函数,则系统不再提供一个无参构造函数 例如 */ public class Dog{ public String name;//这里因为要在测试包里面调用这个变量,因为不在一个包里面,所以要把变量变成共有的 public int health; public int love; public String strain; public Dog(String name,int health,int love,String strain){ this.name=name; this.health=health; this.love=love; this.strain=strain; }//此时无参构造函数没了,如果还想无参构造,那么自己写,因为一个class自动生成一个构造函数,但写了构造函数,那么就不会自动生成了 public Dog(){ } /* this关键字的用法 三点用法: 1、表示对自身的引用! 2、表示用类的成员变量,而非函数参数,注意在函数参数和成员变量同名是进行区分!其实这是第一种用法的特例,比较常用,所以那出来强调一下。 3、用于在构造方法中引用满足指定参数类型的构造器(其实也就是构造方法)。但是这里必须非常注意:只能引用一个构造方法且必须位于开始! 还有就是注意:this不能用在static方法中!所以甚至有人给static方法的定义就是:没有this的方法!虽然夸张,但是却充分说明this不能在static方法中使用! */ public void show(){ System.out.println("宠物的自白:"); System.out.println("我的名字是:"+name+",我的健康值是:"+health+",我和主人的亲密度是:"+love+",我是一值"+strain); } }
package cn.qq.xiangmu.test; import cn.qq.xiangmu.entity.Dog;//因为Dog与test不在一个包里面,所以要引用进来,相当于介绍一下这个包 import cn.qq.xiangmu.entity.penguin; import java.util.Scanner; /* import cn.qq.xiangmu.entity.* 这个意思是直接引用entity包下面的类,不用一个一个写 */ public class Demo01{ public static void main(String[] args) { Dog dog=new Dog("欧欧",100,0,"德国牧羊犬");//调用一个Dog的构造函数 penguin penguin=new penguin(); //dog.name注意这里不能访问,因为不是在一个包下面,所以要把变量变成共有的,如果是在一个包下面,那么不用把变量变成公有的 dog.name="欧欧"; dog.health=100; dog.love=0; dog.strain="德国牧羊犬"; dog.show(); penguin.name="美美"; penguin.health=90; penguin.love=10; penguin.sex="Q妹"; penguin.show(); } }
最后改进得
package cn.qq.xiangmu.entity; public class Dog{ public String name; public int health; public int love; public String strain; public Dog(String name,int health,int love,String strain){ this.name=name; this.health=health; this.love=love; this.strain=strain; } public void show(){ System.out.println("宠物的自白:"); System.out.println("我的名字是:"+name+",我的健康值是:"+health+",我和主人的亲密度是:"+love+",我是一值"+strain); } }
package cn.qq.xiangmu.test; import cn.qq.xiangmu.entity.Dog; import cn.qq.xiangmu.entity.penguin; public class Demo01{ public static void main(String[] args) { Dog dog=new Dog("欧欧",100,0,"德国牧羊犬") Dog.show(); } }
封装
Dog dog=new Dog( );
dog.health=-1000;//属性访问,不合理的赋值,存在缺陷
那么如何解决这种缺陷,使用封装
private int health;//变成私有的,使得不能随意访问变量并对此赋值
面向对象三大特征之一:封装
概念:将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现堆隐藏信息的操作和访问
好处:1.隐藏类的实现细节
2.只能通过规定方法访问数据
3.方便加入控制语句
4.方便实现修改
封装的步骤
1.修改属性的可见性变成private
2.创建共有的getter/setter方法,用于属性的读写
3.在getter/setter方法中加入属性控制语句,对属性值的合法性进行判断
package cn.qq.xiangmu.entity; public class Dog{ private String name;//封装私有化 private int health;//私有化 private int love;//私有化 private String strain;//私有化 //2.提供get,set方法进行属性的读写 public String getName() { return name; } public void setName(String name) { this.name=name; } public int getHealth(){ return health; } public void setHealth(int health) { if(health<0) health=0; if(health>100) health=100;//对属性值的合法性进行判断 this.health=health; } public int love() { return love; } public void setLove(int love) { this.love=love; } public String getStrain() { return strain; } public void setStrain(String strain) { this.strain=strain; } public Dog(String name,int health,int love,String strain){ this.name=name; this.health=health; this.love=love; this.strain=strain; } public void show(){ System.out.println("宠物的自白:"); System.out.println("我的名字是:"+name+",我的健康值是:"+health+",我和主人的亲密度是:"+love+",我是一值"+strain); } }
package cn.qq.xiangmu.test; import cn.qq.xiangmu.entity.Dog; import cn.qq.xiangmu.entity.penguin; public class Demo01{ public static void main(String[] args) { Dog dog=new Dog("欧欧",100,0,"德国牧羊犬");//调用一个Dog的构造函数 /*因为封装的私有化,所以下列变量不可访问 dog.name="欧欧"; dog.health=100; dog.love=0; dog.strain="德国牧羊犬"; dog.show(); */ dog.setHealth(9999); } }
this
如果不存在局部的同名变量,this.是可以省略的。
例如 public void setLove(int love) { this.love=love;//两个同名,this.就不能省略 }
this.后面跟 . 表示访问属性访问方法
调用构造方法,后面不能跟 .
public Dog(String name,int health,int love,String strain){ this.name=name; this.health=health; this.love=love; this.strain=strain; }
这是一个构造函数
调用
public Dog() { this(); }
注意this里面没有参数代表是自身的递归(recursive)调用是死循环,所以要调用对方
public Dog() { this("匿名",50,50,"土狗"); }
首先进入一个无参构造函数,再进入this去调用一个有参构造函数,但这种方法使用不多,但注意this必须使用第一行。
this可以在无参函数里面调用满参函数,也可以在满参函数里面调用无参,但两边同时调用会陷入死循环
public Dog(String name,int health,int love,String strain){ this(); this.name=name; this.health=health; this.love=love; this.strain=strain; }
常量定义
java里面最小的组织单元是类,任何东西是要放在类里面的
比如上面讲到企鹅的性别,如果企鹅性别只有两种的化,一种叫Q妹,一种叫Q崽,那么可以直接在类里面进行定义
好处就是不用再写直接调用即可
static属性和1方法
static可以修饰属性和方法,那这两个有什么区别
有static可以通过类名去访问,不用通过对象而直接通过类名去访问
static修饰的变量是放在方法区里面的静态区的
方法区先出现,堆后出现,后出现的可以访问先出现的
package cn.qq.xiangmu.entity; public class Xxx{ public int a1=1; public static int a2=2;//变量,此时static修饰属性 public void f1() { System.out.println("f1():"); } public static void f2()//static修饰方法 { System.out.println("f2():"); } public void f1() { System.out.println("f1():"+a1+a2);//这个是晚出现的可以访问静态区,且可以不用通过对象访问 } public static void f2()//这是早出现的,也可以访问后期出现的静态区的 { System.out.println("fa():"+a2)//但这里不可以访问a1,因为a1是后出现的,先出现的不能访问后出现的; } /* 非静态的可以访问静态的,静态可以访问静态,但静态不能访问非静态 */ }
package cn.qq.xiangmu.entity; public class Test{ public static void main(String[] args) { System.out.println(Xxx.a2); Xxx.f2(); /* 这里只能访问Xxx里被static修饰的成员的a2和方法的f2, 这里a1访问不了 如果要访问a1,那么必须要通过构造对象来访问 要通过构造Xxx xxx=new Xxx(); xxx.a1;来访问 那么为什么a2,和f2不需要? */ } }
原则:
(静态先出现,非静态后出现,后出现的可以访问先出现的,但先出现的不能访问后出现的)
1.静态可以访问静态
2.非静态可以访问静态
补充:静态访问可以直接通过类名访问,不用通过构造对象,对象访问(Xxx.a1)
static的代码块
package cn.qq.xiangmu.entity; public class Yyy { int a1; public static int a2; public Yyy{ a1=10; } //a1++不能单独写在外面,要么用{a1++},要不就放在放在方法里面 { a1++;//动态代码块,构造对象前,默认会先自动调用一次,构造多少次函数就会调用多少次 //同样静态代码块里面不能访问动态变量 } static{//静态代码块必须写static,要不然就不会走 //静态代码块 该类有访问就唯一调用一次 a2++; } }
package cn.qq.xiangmu.test; import cn.qq.xiangmu.entity.Yyy; import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput; public class Demo03 { public static void main(String[] args) { new Yyy();//先把Yyy里面代码块a++先走一遍再走a1,在走Yyy里面a1=10 System.out.println(Yyy.a2);//通过类名去访问,但这里代码块不会走,因为这里是静态代码块 /* 静态代码块是不会走的 而动态代码块会走,会在构造函数之前走一次 */ } }
总结:
1.{ }普通代码块,很少使用,因为可以在构造函数中编写逻辑代码
2.static{ }静态代码块在开发中经常使用,主要用来初始化静态属性或执行一些前期的初始化逻辑代码