一、封装的概念
面向对象的三大特性:封装、继承、多态。 主要研究的就是封装特性,何为封装呢?
举个例子:
对于电脑这样一个复杂的设备,提供给用户的就只是开关机、通过键盘输入、显示器、USB插孔等,让用户来和计算机进行交互,完成日常事务,但实际上,电脑真正工作的却是CPU、显卡、内存等一些硬件元件。对于计算机使用者而言,不用关心内部核心元件,比如主板上线路是如何布局,CPU内部是如何设计的,用户只需要知道,怎么开机、怎么交互即可。
因此计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘插孔等,让用户可以和计算机进行交互即可。
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
二、访问限定符
Java中提供了四种访问限定符:
default表示默认条件。
同一个包的同一个类:
public class Dog {
public String name;
private double price;
String color;//color的访问权限就是默认的,即default
public static void main(String[] args){
Dog d=new Dog();
System.out.println(d.name);
System.out.println(d.price);
System.out.println(d.color);
}
}
可以通过编译。
同一个包的不同类:
不同包中的非子类:
其他包中的子孙类在后面继承会讲到。
比如:
public:可以理解为一个人的外貌特征,谁都可以看得到。
default:对于自己家族中(同一个包中)不是什么秘密,对于其他人来说就是隐私了。
private:只有自己知道,其他人都不知道。
当修饰类时,访问权限只能用public或者默认。
三、封装扩展之包
1.包的概念:
在面向对象体系中,提出了一个软件包的概念,即:为了更好地管理类,把多个类收集在一起成为一组,称为软件包。 有点类似于目录。比如:为了更好地管理电脑中的歌曲,一种好的方式就是将相同属性的歌曲放在相同文件下,也可以对某个文件夹下的音乐进行更详细的分类。
在Java中也引入了包,包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式,比如:一个包中的类不想被其他包中的类使用。包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在不同的包中即可。
2.导入包中的类
java中已经提供了很多现成的类供我们使用,例如Date类:可以使用java.util.Date导入java.util中的Date类
包中类的使用方式一:
public class TestPackage {
public static void main(String[] args) {
//需求:获取系统的时间
java.util.Date d1=new java.util.Date();
System.out.println(d1.getTime());
}
}
但是假如要再次定义一个d2:
会发现他是飘红的,这也就意味着我们每次都要加上java.util.Date,是非常麻烦的。
优点:一定不会发生冲突。
缺点:使用起来比较麻烦。
包中类的使用方式二:
直接导包:import java.util.Date;
import java.util.Date;
public class TestPackage {
public static void main(String[] args) {
//包中类使用方式二:
Date d3=new Date();
System.out.println(d3.getTime());
}
}
我们想用哪个包的话,就导入哪个包,假如想要操作数组,就import java.util.Arrays,以及后面的集合,要用的话就import java.util.list。这种其实也是比较麻烦的,有一个一劳永逸的方法:import java.util.*,表示当前util包中的所有类都可以在当前类中直接使用。
import java.util.*;
public class TestPackage {
public static void main(String[] args) {
int[] array={1,2,3,4,5};
Arrays.sort(array);
}
}
优点:使用起来非常方便。
缺点:可能会产生冲突。
假设我们还要写数据库类型的代码,也要把相关的包导进来;大多数都要用,为了方便,所以加import.java.sql.*。
import java.util.*;
import java.sql.*;
public class TestPackage {
public static void main(String[] args) {
Date d3=new Date();
System.out.println(d3.getTime());
}
}
为什么会出现这样的问题呢?
这是因为前面我们在导包时,把这个两个包中的所有内容都导入了
如何解决:将Date类的完整路径具体化:采用方式1,具体如下:
包中类的使用方式三:
需求:求100的平方根
在Math这个类中含有,所以可以直接:
System.out.println(Math.sqrt(100));
但是每当我们要用Math中的方法时,都要写上Math.,这也不是非常方便。
==可以使用import static导入包中静态的方法和字段。==就可以直接调用了。
注意事项:import和C++的#include差别很大,C++必须#include来引入其他文件内容,但是java不需要,import只是为了写代码的时候更方便,import更类似于C++的namespace和using。
#include的过程:
而import是代码运行时我们看到那条语句,看到工程当中我们自己没有定义Date类,所以java虚拟机在加载类的时候就会到java.util里边去找Date进行加载。
3.自定义包
基本规则==
1.在文件的最上方加上一个package语句指定该代码在哪个包中。
2.包名需要尽量指定成唯一的名字。
3.包名须和代码路径相匹配,例如创建com.int.demo1的包,那么会存在一个对应的路径com/int/demo1来存储代码。
4.如果一个类没有package语句,则该类被放到一个默认包中。
需求:在工程目录下,创建一个Demo类,让该类位于com.int包中
就创建好了:
4.包的访问权限控制举例
首先我们在Demo类中这样写:
//类修饰符:public
public class Demo {
}
//类修饰符:default(默认)
class Person2{
}
然后在别的包中创建一个类来测试访问权限:
import com.Demo;
import com.Person2;
public class TestPackage {
public void method(){
Demo d=new Demo();
Person2 p=new Person2
}
}
Demo可以正常编译,而Person2则飘红:
就是因为Person2不是public类型的:
如果想让代码通过编译,可以在com底下再重新创建一个Person2类,用public修饰,把之前的删除即可(同一个类中不允许存在两个类都被public修饰)
同时我们再测试一下其他的修饰符:
所以当修饰类时,访问权限只能用public或者默认。(这里的类指的是外部类)
5.常见的包
1.java.lang:系统常见基础类(String、Object),此包从JDK1.1后自动导入。
2.java.lang.reflect:java反射编程包。
3.java.net:进行网络编程开发包。
4.java.sql:进行数据库开发的支持包。
5.java.util:是java提供的工具程序包。(集合类等)非常重要。
6.java.io:I/O编程开发包。