java封装
封装类及类的使用
封装的概念
- 将东西包在一起,然后以新的完整形式呈现出来
- 将方法和字段一起包装到一个单元中,单元以类的形式实现
- 信息隐藏,隐藏对象的实现细节,不让外部直接访问到
- 将数据和方法包装进类中,加上具体实现的隐藏(访问修饰符)共同被称作封装。其结果是一个同时带有特征和行为的数据类型
定义类,定义其属性、方法的过程称为封装类
定义类
class Student {}
class Student //定义类
{
int age; //定义属性
String name;
double score;
void introduce(){ //定义方法,同等于C语言的函数
System.out.println("name:"+name+",age:"+age+",score:"+score);
}
void testFunc(){
System.out.println("testFunc");
}
}
类的使用
Student stu1 = new Student();
- 通过一个类实例化一个对象
- 类就只是一个模板,里面只有属性跟方法,里面具体的值是不清楚的
- 类不能直接使用,不能直接访问变量,需要先实例化,就是需要申请一个空间,才能给属性赋值,使用类的方法
class Student
{
int age;
String name;
double score;
void introduce(){
System.out.println("name:"+name+",age:"+age+",score:"+score);
}
void testFunc(){
System.out.println("testFunc");
}
}
public class Test1 {
public static void main(String[] args) {
Student stu1 = new Student();//通过一个类实例化一个对象
//类就只是一个模板,里面只有属性跟方法,里面具体的值是不清楚的
//类不能直接使用,不能直接访问变量,需要先实例化,就是需要申请一个空间,才能给属性赋值,使用类的方法
stu1.age = 20;
stu1.name = "张三";
stu1.score = 99.5;
stu1.introduce();
}
}
访问修饰符
规定类,成员属性,方法访问范围的关键字
信息隐藏是OOP最重要的功能之一,也是使用访问修饰符的原因
信息隐藏的原因包括:
- 对模块的任何实现细节所作的更改不会影响使用该模块的代码
- 防止用户意外修改数据
- 使模块易于维护和使用(大概类比为电脑配件)
访问修饰符:
public:该类或非该类均可以访问
private:只有该类可以访问
protected:该类及其子类的成员可以访问,同一个包中的类也可以访问
默认:同一个包中的类也可以访问
位置 | private | 默认 | protected | public |
---|---|---|---|---|
同一个类 | 是 | 是 | 是 | 是 |
同一个包内的类 | 否 | 是 | 是 | 是 |
不同包内的子类 | 否 | 否 | 是 | 是 |
不同包并且不是子类 | 否 | 否 | 否 | 是 |
private 修饰符示例
class Student
{
int age;
String name;
double score;
private int sex; //不能在类外通过实例对象访问属性变量,只能通过在本类里的函数访问
void person(int finalsex){
sex = finalsex;
}
void introduce(){
System.out.println("name:"+name+" age:"+age+" sex:"+sex+" score:"+score);
}
void testFunc(){
System.out.println("testFunc");
}
}
public class Test1 {
public static void main(String[] args) {
Student stu1 = new Student();//通过一个类实例化一个对象
stu1.age = 20;
stu1.name = "张三";
stu1.score = 99.5;
stu1.person(30);
stu1.introduce();
}
}
执行结果:
属性封装的实现
- 修改属性的可见性来限制对属性的访问
- 为每个属性创建一对赋值方法(setter)和取值(getter)方法,用于公开对这些属性的访问接口
- 在setter和getter方法中,根据需要加入对属性操作的原则
代码实现:
class Student
{
private int sex;
public void setsex(int finalsex){ //赋值方法
sex = finalsex;
}
public int getsex(){ //取值方法
return sex;
}
}
public class Test1 {
public static void main(String[] args) {
Student stu1 = new Student();
stu1.setsex(10);//赋值
int a = stu1.getsex();//取值
System.out.println("sex:"+a);
}
}
执行结果:
方法封装的目的
- 隐藏方法实现细节(方法体),向外部提供公开接口(方法头),以供安全调用,简化调用,方便修改维护
- 根据需要,可以私有化方法,以供内部使用
class Student
{
private int age;
private void myage(int myage){ //私有化方法,对属性修改
age = myage;
}
public void setsex(int realage){ //赋值方法
age = realage;
}
public int getsex(){ //取值方法
myage(18); //调用私有化的方法对属性更改,让赋值方法改变的值发生自己想要的改变
return age;
}
}
public class Test1 {
public static void main(String[] args) {
Student stu1 = new Student();
stu1.setsex(36);
System.out.println("sex:"+stu1.getsex());
}
}
UML类图
UML是一种建模语言
- 类的命名尽量要用应用领域中的术语,应用明确、无歧义,以利于相互交流和理解
- 类的属性、操作中的可见性使用+、#、-分别表示public、protected、private
-表示private
#表示protected
~表示default,也就是包权限
_下划线表示static
斜体表示抽象
构造方法
类构造方法的概念和作用
- 构造方法负责对象初始化工作,为对象的属性赋合适的初始值
- 创建对象时,其类的构造方法确保在用户操作对象之前,系统保证初始化的进行
构造方法的语法规则
- 构造方法名与类名一致
- 没有返回类型
- 方法实现主要为字段赋初值
构造方法的调用
- 构造方法的调用很特别:new操作符(实例化对象时,自动被调用)
Java系统保证每个类都有构造方法
Student(){}
Java系统保证每个类都有构造方法,会默认添加这个方法
java语言中,方法是可重载的,类比C语言中函数名一样,参数列表不同,在C语言中不允许
class Student
{
int age;
String name;
double score;
Student(){
System.out.println("构造方法一被调用");
}
//Java系统保证每个类都有构造方法,会默认添加这个方法
//java语言中,方法是可重载的,类比C语言中函数名一样,参数列表不同,在C语言中不允许
Student(int newage,String newname){
System.out.println("构造方法二被调用");
age = newage;
name = newname;
}
Student(int newage,String newname, double newscore){
System.out.println("构造方法三被调用");
age = newage;
name = newname;
score = newscore;
}
}
public class Test1 {
public static void main(String[] args) {
Student stu1 = new Student();
Student stu2 = new Student(20,"wang");
Student stu3 = new Student(18,"zhang",56.8);
}
}
执行结果:
this关键字
this关键字特点:
-
在类的方法中,使用this关键字代表的是调用此方法的对象的引用
System.out.println(this.name);
class Student
{
int age;
String name;
double score;
void testThis(){
System.out.println(this.name);
}
Student(int newage,String newname, double newscore){
System.out.println("构造方法被调用");
age = newage;
name = newname;
score = newscore;
}
}
public class Test1 {
public static void main(String[] args) {
Student stu1 = new Student(18,"zhang",56.8);
stu1.testThis();
}
}
执行结果:
-
this可以看做是一个变量,它的值是当前对象的引用
Student stutmp = null; stutmp = this; System.out.println(stutmp.age);
class Student
{
int age;
String name;
double score;
void testThis(){
Student stutmp = null;
stutmp = this;
System.out.println(stutmp.age);
}
Student(int newage,String newname, double newscore){
System.out.println("构造方法被调用");
age = newage;
name = newname;
score = newscore;
}
}
public class Test1 {
public static void main(String[] args) {
Student stu1 = new Student(18,"zhang",56.8);
stu1.testThis();
}
}
执行结果:
-
使用this可以处理方法中的成员变量和形参同名的问题
Student(int age,String name, double score){ System.out.println("构造方法被调用"); this.age = age; this.name = name; this.score = score; }
class Student
{
int age;
String name;
double score;
void testThis(){
Student stutmp = null;
stutmp = this;
System.out.println(stutmp.score);
}
Student(int age,String name, double score){
System.out.println("构造方法被调用");
this.age = age;
this.name = name;
this.score = score;
}
}
public class Test1 {
public static void main(String[] args) {
Student stu1 = new Student(18,"zhang",56.8);
stu1.testThis();
}
}
-
当在方法内需要用到调用到该方法的对象时,就可以用this
-
在类的构造方法中可以调用this([参数列表])来调用该类的指定构造方法
-
在类实例化调用类里的构造方法的时候,this()只能放在开头,调一次
-
this()不带参数的调用:
-
class Student
{
int age;
String name;
double score;
void testThis(){
Student stutmp = null;
stutmp = this;
System.out.println(stutmp.score);
}
Student(){
System.out.println("构造方法一被调用");
}
Student(int newage,String newname){
System.out.println("构造方法二被调用");
age = newage;
name = newname;
}
Student(int age,String name, double score){
this();
System.out.println("构造方法三被调用");
this.age = age;
this.name = name;
this.score = score;
}
}
public class Test1 {
public static void main(String[] args) {
Student stu1 = new Student(18,"zhang",56.8);
stu1.testThis();
}
}
执行结果:
this(23,“wang”)带参数的调用:
class Student
{
int age;
String name;
double score;
void testThis(){
Student stutmp = null;
stutmp = this;
System.out.println(stutmp.score);
}
Student(){
System.out.println("构造方法一被调用");
}
Student(int newage,String newname){
System.out.println("构造方法二被调用");
age = newage;
name = newname;
}
Student(int age,String name, double score){
this(23,"wang");
System.out.println("构造方法三被调用");
this.age = age;
this.name = name;
this.score = score;
}
}
public class Test1 {
public static void main(String[] args) {
Student stu1 = new Student(18,"zhang",56.8);
stu1.testThis();
}
}
执行结果:
static关键字的特点
-
用来修饰类的成员——修饰成员变量的称为类变量(静态变量)
Student.data = 20; //靠static关键字修饰变量,可以通过Student.data = 20;这样访问
class Student
{
private int age; //隐藏了的,在main里不能 stu1.age = 10;这样直接访问,需要在类里做个赋值,取值方法,在来操作
String name;
double score;
static int data;
Student(int age,String name, double score){
this.age = age;
this.name = name;
this.score = score;
}
void introduce(){
System.out.println("name:"+name+",age:"+age+",score:"+score);
}
}
public class Test1 {
public static void main(String[] args) {
Student stu1 = new Student(18,"zhang",56.8);
stu1.score = 10;
Student.data = 20;//靠static关键字修饰变量,可以通过Student.data = 20;这样访问
}
}
-
修饰成员方法称之为类方法(静态方法)
- 加了static修饰符的方法调用:
public class Test1 {
public static void main(String[] args) {
System.out.println("ret="+add(2,4));
}
static int add(int a,int b){
return a+b;
}
}
- 不加static修饰符的方法调用:
public class Test1 {
public static void main(String[] args) {
Test1 t = new Test1();
System.out.println("ret="+t.add(2,4));
}
int add(int a,int b){
return a+b;
}
}
-
当类被加载的时候就会被加载,优先于对象的存在
-
用来修饰语句块——称之为静态代码块,先于构造方法之前执行,只会执行一次,用来对静态成员做初始化。
static{ System.out.println("静态代码块"); data = 100; }
class Student
{
private int age; //隐藏了的,在main里不能 stu1.age = 10;这样直接访问
String name;
double score;
static int data;
Student(int age,String name, double score){
System.err.println("构造方法");
this.age = age;
this.name = name;
this.score = score;
}
static{
System.out.println("静态代码块");
data = 100;
}
void introduce(){
System.out.println("name:"+name+",age:"+age+",score:"+score);
}
}
public class Test1 {
public static void main(String[] args) {
Student stu1 = new Student(18,"zhang",56.8);
stu1.score = 10;
Student.data = 20;//靠static关键字修饰变量,可以通过Student.data = 20;这样访问
System.out.println("ret="+Student.data);
}
}
执行结果:
-
调用的时候可以直接通过类名.成员来进行访问
Student.data = 20;
注意:
- 静态方法中只能访问外部的静态成员
使用案例:
class Student
{
String name;
static int data;
static void test{
System.out.println(data);
}
}
错误使用案例:
class Student
{
String name;
static int data;
static void test{
System.out.println(name);
}
}
- 静态方法中不能出现this关键字
方法的重载
多数程序设计要求为每个方法(函数)提供一个独一无二的方法名,不存在方法重载的概念,但在Java中,规定方法签名是解析方法的规则而不是方法名,为为方法重载开创了条件。
方法重载使得在一个类中,方法名相同而参数列表不同的方法可同时存在,代表相似的行为或功能。
public class Test1 {
public static void main(String[] args) {
int i = 10;
char c = 'z';
String str = "hello";
System.out.println(i);
System.out.println(c);
System.out.println(str);
}
}
执行结果:
重载overload概念:同一个类中,同名不同参数的方法称为重载方法
注意:仅有返回值不同的方法不能称为重载
包(package)
打包的意义:
- 标准Java库是有一系列包组成,包括Java.lang java.util java.net等等。
- 标准Java包就是层次型包结构,就如同硬盘上嵌套的子目录一样,我们可以使用嵌套层次结构来组织包。
- Java的包是为了更好的规划代码,防止命名冲突和混乱,所以Java出现了打包机制。
- 当把类组织起来放进一个包内之时,也就给包中的成员赋予了相互访问的权限,您就拥有了该包内的程序代码
- 包访问权限把类聚集在一个包中这一做发提供了意义和理由
包的命名
为保证包名唯一性,所以在给包命名时一般使用互联网公司域名倒置来命名。
一个类可以使用同一个包中的所有类
一个类可以使用其它包中的所有公开类
怎么使用其它包中的公开类
- 在每个类签名加上完整包名,例如:
java.util.Date today = new java.util.Date();
- 更简洁更通用的方式:使用import语句来导包(eclipse Ctrl+Shift+o)
import java.util.Date;
...........
Date today = new Date();
- 可以import特定类,也可以导入整个包,通过在源代码文件的顶部(在打包语句后)使用import语句来实现import java.util.*;
代码测试
com.yang.learn
Test.java
package com.yang.learn;
public class Test {
public static void main(String[] args) {
Demo dm = new Demo();
dm.age = 20;
dm.printfdata();
com.yang.use.Demo dm2 = new com.yang.use.Demo();
dm2.name = "zhang";
dm2.printfinfo();
}
}
Demo.java
package com.yang.learn;
public class Demo {
int age;
void printfdata(){
System.out.println("同一个包里的age="+age);
}
}
com.yang.use
Demo.java
package com.yang.use;
public class Demo {
public String name;
public void printfinfo()
{
System.out.println("不同包里的name="+name);
}
}
执行结果:
import com.yang.use.Demo1;
应用不同包里的类,不同包里,同包里的类名不要命名成样的
Test.java
package com.yang.learn;
import com.yang.use.Demo1;
public class Test {
public static void main(String[] args) {
Demo dm = new Demo();
dm.age = 20;
dm.printfdata();
Demo1 dm2 = new Demo1();
dm2.name = "zhang";
dm2.printfinfo();
}
}