所谓的包实际上指的就是文件夹。
定义包
// An highlighted block
package com.yootk.demo;
public class Hello{
public static void main(String args[]){
System.out.println("hello world");
}
}
由上可知,Hello类定义在了一个com.yootk.demo包中
打包编译:javac -d .Hello.java
使用import
// An highlighted block
package com.yootk.demo;
import com.yootk.util.Message;
public class Hello{
public static void main(String args[]){
System.out.println("hello world");
}
}
如果存在多个*.java 文件中的类相互引用的情况,为了解决编译顺序的问题,提供了通配符 的操作:javac -d ..java,这样就会自动根据代码的调用顺序进行程序编译。
如果不使用通配符*,则进行二步操作
NO. | 范围 | private | default | protected | public |
---|---|---|---|---|---|
1 | 在同一个包的同一个类 | ✔ | ✔ | ✔ | ✔ |
2 | 同一包的不同类 | ✔ | ✔ | ✔ | |
3 | 不同包的子类 | ✔ | ✔ | ||
4 | 不同包的非子类 | ✔ |
简单理解为:private只能在一个类中访问;default只能在一个包中访问;protected在不同包的子类中;public为所有都可以。
定义com.yootk.demoa.A类
// An highlighted block
package com.yootk.demoa;
public class A{
protected String info = "Hello";
}
定义com.yootk.demoa.B类
// An highlighted block
package com.yootk.demoa;
import com.yootk.demoa.A
public class B extends A{
public void print(){
System.out.println("A类的info = "+super.info);
}
}
那么一般情况下如何去选择权限呢?
答:属性声明主要使用private权限;方法声明主要使用public权限。
在之前大部分的属性定义时都使用了private进行声明,而对于构造方法也可以使用private声明,则此时的构造方法就被私有化了。
构造方法非私有化
// An highlighted block
class Singleton{
public void print(){
System.out.println("Hello");
}
}
public class Test {
public static void main(String[] args) {
Singleton singleton = null;
singleton = new Singleton();
singleton.print();
}
}
私有化构造方法
// An highlighted block
package chapter5;
class Singleton{
private Singleton(){
}
public void print(){
System.out.println("Hello");
}
}
public class Test {
public static void main(String[] args) {
Singleton singleton = null;
singleton = new Singleton();
singleton.print();
}
}
程序出现了编译错误,因为构造方法被私有化了,无法在外部调用,即无法在外部实例化Singleton类的对象。
现在就需要思考:在保证Singleton类中的构造方法不修改不增加,以及print()方法不修改的情况下,如何操作才可以让类的外部通过实例化对象去调用print()方法?
思考过程一:使用private 访问权限定义的操作只能被本类所访问,外部无法调用,现在既然构造方法被私有化,就证明,这个类的构造方法只能被本类所调用,即只能在本类中产生本类实例化对象
// An highlighted block
package chapter5;
class Singleton{
Singleton instance = new Singleton();
private Singleton(){
}
public void print(){
System.out.println("Hello");
}
}
思考过程二:对于一个类中的普通属性,默认情况下一定要在本类存在实例化对象后才可以进行调用,可是本程序在Singleton类的外部无法产生实例化对象,就必须想一个办法,让Singleton类中的instance属性可以在没有Singleton类实例化对象时来进行调用。因此想到可以使用static完成。
// An highlighted block
package chapter5;
class Singleton{
static Singleton instance = new Singleton();
private Singleton(){
}
public void print(){
System.out.println("Hello");
}
}
public class Test {
public static void main(String[] args) {
Singleton singleton = null;
singleton = Singleton.instance; 直接这样获得类的实例化对象
singleton.print();
}
}
结果:Hello
思考过程三:首先按之前的学习,类中的全部属性都应该封装,然后通过getter、setter去访问获取,只不过getter方法也定义为static型。
// An highlighted block
package chapter5;
class Singleton{
static Singleton instance = new Singleton();
private Singleton(){
}
public void print(){
System.out.println("Hello");
}
public static Singleton getInstance(){
return instance;
}
}
public class Test {
public static void main(String[] args) {
Singleton singleton = null;
singleton = Singleton.getInstance(); 直接这样获得类的实例化对象
singleton.print();
}
}
如果要调用类中定义的操作,那么很显然需要一个实例化对象,这时就可以在类的内部使用static方式来定义一个公共的对象,并且每一次通过static方法返回唯一的一个对象,这样外部不管有多少次调用,最终一个类只能产生唯一的一个对象,这样的设计就属于单例设计模式。
不过现在还有一个小问题,就是以下代码也可以使用
// An highlighted block
class Singleton{
private static Singleton instance = new Singleton();
private Singleton(){
}
public void print(){
System.out.println("Hello");
}
public static Singleton getInstance(){
instance = new Singleton(); //重新实例化对象
return instance;
}
}
public class Test {
public static void main(String[] args) {
Singleton singleton = null;
singleton = Singleton.getInstance();
singleton.print();
}
}
所以可以尝试加一个final关键字
// An highlighted block
class Singleton{
private final static Singleton instance = new Singleton(); //在这一行加就好了
private Singleton(){
}
public void print(){
System.out.println("Hello");
}
public static Singleton getInstance(){
return instance;
}
}
结果:Hello
多例设计模式其实就是有限的定义多个对象。不管是单例设计还是多例设计,有一个核心不可动摇,就是构造方法私有化。
// An highlighted block
class Sex{
private String title;
private static final Sex MALE = new Sex("男");
private static final Sex FEMALE = new Sex("女");
private Sex(String title){
this.title = title;
}
@Override
public String toString(){
return this.title;
}
public static Sex getInstance(int ch){
switch (ch){
case 1:
return MALE;
case 2:
return FEMALE;
default:
return null;
}
}
}
public class Test {
public static void main(String[] args) {
Sex sex = null;
sex = Sex.getInstance(2);
System.out.println(sex);
}
}
执行结果:女
在JDK1.7之前,switch只能利用int或者char进行判断,正因为如果纯粹是数字或字符意义不明确,所以增加了String的支持。
// An highlighted block
class Sex{
private String title;
private static final Sex MALE = new Sex("男");
private static final Sex FEMALE = new Sex("女");
private Sex(String title){
this.title = title;
}
@Override
public String toString(){
return this.title;
}
public static Sex getInstance(String ch){
switch (ch){
case "man":
return MALE;
case "woman":
return FEMALE;
default:
return null;
}
}
}
public class Test {
public static void main(String[] args) {
Sex sex = null;
sex = Sex.getInstance("man");
System.out.println(sex);
}
}
执行结果:男