一、封装
- 1.概念
将类的某些特征隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。 - 2.好处
a.只能通过规定的方法访问数据;
b.隐藏类的实现细节,方便修改和实现;
c.高内聚,低耦合。高内聚:类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。 - 3.封装的实现步骤
a.修改属性的可见性(设为private);
b.创建getter/setter方法(用于属性的读写);
c.在getter/setter方法中加入属性控制语句(对属性值的合法性进行判断)。
下面看一个例子:
public class Telphone {
private float screen;
private float cpu;
private float mem;
public float getScreen(){
return screen;
}
public void setScreen(float newScreen){
screen=newScreen;
}
public Telphone(){
System.out.println("无参的构造方法就执行了!");
}
public Telphone(float newScreen,float newCpu,float newMem){
screen=newScreen;
cpu=newCpu;
mem=newMem;
System.out.println("有参的构造方法执行了!");
}
}
----------
public class InitailTelphone {
public static void main(String[] args) {
Telphone phone = new Telphone();
Telphone phone2=new Telphone(5.0f,1.4f,2.0f);
phone2.setScreen(6.0f);
System.out.println("screen:"+phone2.getScreen());
}
}
输出结果:
无参的构造方法就执行了!
有参的构造方法执行了!
screen:6.0
1.1、使用包管理java中的类
- 1.包的作用
管理java文件,解决同名文件的冲突。 - 2.定义包
package 包名
注意:
a.必须放在java源程序的第一行;
b.包名间可以使用“.”号隔开;
例如:com.xupt.test - 3.系统中的包
java.(功能).(类)
java.lang.(类)包含java语言基础的类;
java.util.(类)包含java语言中各种工具类;
java.io.(类)包含输入、输出相关功能的类。 - 4.包的使用
a.可以通过import关键字,在某个文件使用其他文件中的类。
import com.xupt.test
b.java中,包的命名规范全是小写字母拼写。
c.使用的时候不但可以加载某个包下的所有文件:
com.xupt.*
也可以加载某个子包下的所有文件:
com.xupt.music.*
1.2、java中的访问修饰符
- 访问修饰符的总结:
访问修饰符 | 本类 | 同包 | 子类 | 其他 |
---|---|---|---|---|
private | √ | |||
默认 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
1.3、java中的this关键字
- 1.this关键字代表当前对象
this.属性 操作当前对象的属性
this.方法 操作当前对象的方法 - 2.封装对象的属性的时候,经常会使用this关键字。
- 3.普通方法中:this总是指向调用该方法的对象;
构造方法中:this总是指向正要初始化的对象。
1.4 java中的内部类
- 1.内部类
一般情况下,把类定义成独立的单元;有些情况下,把一个类定义在另一个类的内部,即内部类。 - 2.内部类的作用:
提供了更好的封装。只能让外部类直接访问,不允许同一个包的其他类直接访问;内部类可以直接访问外部类的私有属性,内部类被当成外部类的成员。但外部类不能访问内部类的内部属性。
java中的成员内部类
- 内部类中最常见的就是成员内部类,也称为普通内部类。
举个例子:
运行结果:
访问外部类中的a:99
访问内部类中的b:2
从上面的代码中我们可以看到,成员内部类的使用方法:
1、 Inner 类定义在 Outer 类的内部,相当于 Outer 类的一个成员变量的位置,Inner 类可以使用任意访问控制符,如 public 、protected 、 private 等
2、 Inner 类中定义的 test() 方法可以直接访问 Outer 类中的数据,而不受访问控制符的影响,如直接访问 Outer 类中的私有属性a
3、 定义了成员内部类后,必须使用外部类对象来创建内部类对象,而不能直接去 new 一个内部类对象,即:内部类 对象名 = 外部类对象.new 内部类( );
4、 编译上面的程序后,会发现产生了两个 .class 文件。一个是外部类的,一个是外部类的。
* 注意:
1、外部类是不能直接使用内部类的成员和方法。
可先创建内部类的对象,然后通过内部类的对象来访问其成员变量和方法。
2、如果外部类和内部类具有相同的成员变量或方法,内部类默认访问自己的成员变量或方法,如果要访问外部类的成员变量,可以使用 this 关键字。如:
运行结果:
访问外部类中的b:1
访问内部类中的b:2
练习:
//外部类HelloWorld
public class HelloWorld{
//外部类的私有属性name
private String name = "imooc";
//外部类的成员属性
int age = 20;
//成员内部类Inner
public class Inner {
String name = "爱慕课";
//内部类中的方法
public void show() {
System.out.println("外部类中的name:" + HelloWorld.this.name);
System.out.println("内部类中的name:" + name);
System.out.println("外部类中的age:" + age);
}
}
//测试成员内部类
public static void main(String[] args) {
//创建外部类的对象
HelloWorld o = new HelloWorld ();
//创建内部类的对象
Inner inn = o.new Inner();
//调用内部类对象的show方法
inn.show();
}
}
程序运行结果:
外部类中的name:imooc
内部类中的name:爱慕课
外部类中的age:20
java中的静态内部类
- 静态内部类是用static修饰的内部类,特点:
1、静态内部类不能直接访问外部类的非静态成员,但可以通过 new 外部类().成员 的方式访问 ;
2、 如果外部类的静态成员与内部类的成员名称相同,可通过“类名.静态成员”访问外部类的静态成员;如果外部类的静态成员与内部类的成员名称不相同,则可通过“成员名”直接调用外部类的静态成员;
3、 创建静态内部类的对象时,不需要外部类的对象,可以直接创建 内部类 对象名= new 内部类()。
运行结果:
访问外部类中的b:1
访问内部类中的b:2
练习:
//外部类
public class HelloWorld {
// 外部类中的静态变量score
private static int score = 84;
// 创建静态内部类
public static class SInner {
// 内部类中的变量score
int score = 91;
public void show() {
System.out.println("访问外部类中的score:" + HelloWorld.score);
System.out.println("访问内部类中的score:" + score);
}
}
// 测试静态内部类
public static void main(String[] args) {
// 直接创建内部类的对象
SInner si = new SInner();
// 调用show方法
si.show();
}
}
程序运行结果:
访问外部类中的score:84
访问内部类中的score:91
java中的方法内部类
- 方法内部类就是内部类定义在外部类的方法中,方法内部类只在该方法的内部可见,即只在该方法内可以使用。
- 注意:
由于方法内部类不能在外部类的方法以外的地方使用,因此方法内部类不能使用访问控制符和 static 修饰符。
练习:
//外部类
public class HelloWorld {
private String name = "爱慕课";
// 外部类中的show方法
public void show() {
// 定义方法内部类
class MInner {
int score = 83;
public int getScore() {
return score + 10;
}
}
// 创建方法内部类的对象
MInner mi = new MInner();
// 调用内部类的方法
int newScore=mi.getScore();
System.out.println("姓名:" + name + "\n加分后的成绩:" + newScore);
}
// 测试方法内部类
public static void main(String[] args) {
// 创建外部类的对象
HelloWorld mo = new HelloWorld();
// 调用外部类的方法
mo.show();
}
}
程序运行结果:
姓名:爱慕课
加分后的成绩:93
二、继承
- 类是对对象的抽象,继承是对某一批类的抽象,从而实现对现实世界更好的建模。
- 提高代码的复用性。
- 子类继承父类,可以得到父类的全部属性和方法(除了父类中的构造方法)。
- java中只有单继承,没有像c++那样的多继承。多继承会引起混乱,使得继承链过于复杂,系统难于维护。
- java中的多继承可以通过接口来实现。
例子:
public class Animal {
public int age;
public String name;
public void eat(){
System.out.println("动物吃吃吃!");
}
}
----------
public class Dog extends Animal {
}
----------
public class Initail {
public static void main(String[] args) {
// TODO Auto-generated method stub
Dog dog=new Dog();
dog.age=10;
dog.name="小狗";
dog.eat();
System.out.println(dog.age);
System.out.println(dog.name);
}
}
java中的方法重写
- 什么是方法的重写:
如果子类对继承父类的方法不满意,是可以重写父类继承的方法的,当调用方法时会优先调用子类的方法。 - 重写方法必须和被重写方法具有相同方法名称、参数列表和返回类型。
- 重写方法不能使用比被重写方法更严格的访问权限(由于多态)。
继承的初始化顺序
- 先初始化父类再初始化子类;
- 先执行初始化对象中的属性,再执行构造方法中的初始化。
例子一:
public class Animal {
public int age;
public String name;
public void eat(){
System.out.println("动物具有吃东西的能力!");
}
public Animal(){
System.out.println("Animal父类构造器执行了!");
}
}
----------
public class Dog extends Animal {
public Dog(){
System.out.println("Dog子类构造器执行了!");
}
}
----------
public class Initail {
public static void main(String[] args) {
// TODO Auto-generated method stub
Dog dog=new Dog();
dog.age=10;
dog.name="小狗";
dog.eat();
}
}
程序运行过结果:
Animal父类构造器执行了!
Dog子类构造器执行了!
动物具有吃东西的能力!
从中可以发现,程序只是创建了子类对象,但是他是先执行了父类的构造方法,然后才执行子类的构造方法。所以在创建对象的时候,优先创建父类对象,然后才会创建我们的子类对象。
例子二:
public class Animal {
public int age=10;
public String name;
public void eat(){
System.out.println("动物具有吃东西的能力!");
}
public Animal(){
System.out.println("Animal父类构造器执行了!");
age=20;
}
}
----------
public class Dog extends Animal {
public Dog(){
System.out.println("Dog子类构造器执行了!");
}
}
----------
public class Initail {
public static void main(String[] args) {
// TODO Auto-generated method stub
Animal an=new Animal();
System.out.println("animal age:"+an.age);
Dog dog=new Dog();
dog.age=10;
dog.name="小狗";
dog.eat();
}
}
程序运行结果:
Animal父类构造器执行了!
animal age:20
Animal父类构造器执行了!
Dog子类构造器执行了!
动物具有吃东西的能力!
从中可以发现:先执行初始化对象中的属性,再执行构造方法中的初始化。后执行的属性覆盖先执行的
属性。
java中的final关键字的使用
- final关键字做标识有“最终的”含义。
- final可以修饰类、方法、属性和变量。
1.修饰类:则该类不允许被继承;
2.修饰方法:则该方法不允许被覆盖(重写);
3.修饰属性:则该类的属性不会进行隐式的初始化(类的初始化属性必须有值)或在构造方法中赋值;
4.修饰变量:则该变量的值只能赋一次值,即为常量。
Java中的super关键字的使用
- super关键字:在对象的内部使用,可以代表父类对象。
1.访问父类的属性:
super.age
2.访问父类的方法:
super.eat() - super的应用
1.子类的构造过程当中必须调用其父类的构造方法。
2.如果子类的构造方法当中没有显示调用父类的构造方法,则系统会默认调用父类无参的构造方法(通过super关键字)。
3.如果显示的调用构造方法,必须写在子类的构造方法的第一行(super();)。
4.如果子类构造方法中既没有显示调用父类的构造方法,而父类又没有无参的构造方法,则编译出错。
java中的Object类
- Object类是所有类的父类,如果一个类没有使用extends关键字明确标识继承另外一个类,那么这个类默认继承Object类。Object类中的方法,适合所有子类。
- 几个重要的方法
1.toString()方法:
在Object类中定义toString()方法的时候,返回的是对象的哈希code码(对象地址字符串)。
可以通过重写toString()方法表示出对象的属性。
2.equals()方法:
比较的是对象的引用是否指向同一块内存地址。
三、多态
- 多态:对象的多种形态。多态是oop中的一个重要特性,主要是用来实现动态联编的,就是程序的最终状态只有在执行过程中才被决定而非在编译期间就决定了。这对于大型系统来说能提高系统的灵活性和扩展性。
- 引用变量的两种类型:
1.编译时类型:模糊一点,一般是一个父类;由声明时的类型决定。
2.运行时类型:运行时,具体是那个子类就是哪个子类;由实际对应的对象类型决定。 - 多态类型:
1.引用多态:
a.父类的引用可以指向本类的对象。
b.父类的引用可以指向子类的对象。
2.方法多态:
a.创建本类对象时,调用的方法为本类方法。
b.创建子类对象时,调用的方法为子类重写的方法或者继承的方法。 - 例子:
public class Animal {
public void eat(){
System.out.println("动物具有吃的能力");
}
}
----------
public class Dog extends Animal {
public void eat(){
System.out.println("狗是吃肉的");
}
public void watchDoor(){
System.out.println("狗具有看门的能力");
}
}
----------
public class Cat extends Animal {
}
----------
public class Initail {
public static void main(String[] args) {
// TODO Auto-generated method stub
Animal obj1 = new Animal();
Animal obj2 = new Dog();//父类的引用是可以指向子类对象的
Animal obj3 = new Cat();
//Dog obj3 = new Animal();//错
obj1.eat();//
obj2.eat();/
obj3.eat();
//obj2.watchDog();//watchDog()是子类独有的方法,并不是从父类继承来的,此时在main函数中就不能通过父类的引用调用子类独有的方法。
}
}
程序运行结果:
动物具有吃的能力
狗是吃肉的
动物具有吃的能力
引用类型转换
- 向上类型转换(隐式/自动类型转换),是小类型到大类型的转换。
- 向下类型转换(强制类型转换),是大类型到小类型。
- instanceof运算符,来解决引用对象的类型,避免类型转换的安全性问题。
Dog dog = new Dog();
Animal animal = dog;//向上类型转换 自动类型转换
Dog dog2 = (Dog)animal;//向下类型转换 强制类型转换
Cat cat = (Cat)animal;//1.编译时,Cat类型 2.运行时,Dog类型 故报错!可通过instanceof运算符避免类型转换的安全性问题。
if(animal instanceof Cat){
Cat cat = (Cat)animal;//1.编译时 Cat类型 2.运行时 Dog类型
}else{
System.out.println("无法进行类型转换 转换成Cat类型");
}//运行结果:无法进行类型转换 转换成Cat类型
----------
if(animal instanceof Dog){
Dog dog2 = (Dog)animal;
}else{
System.out.println("无法进行类型转换 转换成Dog类型");
}
抽象类
- 语法定义:
抽象类前使用abstract关键字修饰,则该类为抽象类。 - 应用场景:
1.在某些情况下,某个父类只是知道其子类应该包含怎样的方法,但无法准确知道这些子类如何实现这些方法。
2.从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为子类的模板,从而避免了子类设计的随意性。 - 作用:
限制规定子类必须实现某些方法,但不关注实现细节。 - 使用规则:
1.abstract关键字定义抽象类。
2.abstract定义抽象方法,只有声明,不需要实现。
3.包含抽象类方法的类是抽象类。
4.抽象类中可以包含普通方法,也可以没有抽象方法。
5.抽象类不能直接创建,可以定义引用变量。 - 例子
public abstract class Telphone {
public abstract void call();
public abstract void message();
}
----------
public class CellPhone extends Telphone {
@Override
public void call() {
// TODO Auto-generated method stub
System.out.println("通过键盘来打电话");
}
@Override
public void message() {
// TODO Auto-generated method stub
System.out.println("通过键盘来发短信");
}
}
----------
public class SmartPhone extends Telphone {
@Override
public void call() {
// TODO Auto-generated method stub
System.out.println("通过语音打电话");
}
@Override
public void message() {
// TODO Auto-generated method stub
System.out.println("通过语音发短信");
}
}
----------
public class Initail {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Telphone tel1 = new CellPhone();
tel1.call();
tel1.message();
Telphone tel2 = new SmartPhone();
tel2.call();
tel2.message();
程序运行结果:
通过键盘来打电话
通过键盘来发短信
通过语音打电话
通过语音发短信
java中的接口
- 接口概念
1.接口可以理解为一种特殊的类,由全局常量和公共的抽象方法所组成。
2.类是一种具体实现体,而接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部数据,也不关心这些类里方法的实现细节,它只是规定这些类里必须提供某些方法。 - 接口定义
1.和类定义不同,定义接口不再使用class关键字,而是使用interface关键字。
2.接口定义的基本语法:
[修饰符] interface 接口名 [extends 父接口1,extends 父接口2……]{
零个到多个常量定义…
(接口中的属性是常量,即使定义时不添加public static final修饰符,系统也会自动加上。)
零个到多个抽象方法的定义…
(接口中的方法只能是抽象方法,即使定义时不添加public abstract修饰符,系统也会自动加上。)
}
注意
接口就是用来被继承、被实现的,修饰符一般建议用public。不能使用private和protected修饰接口!
- 使用接口
一个类可以实现一个或者多个接口,实现接口使用implements关键字。java中一个类只能继承一个父类,是不够灵活的,通过实现多个接口可以做补充。
继承父类实现接口的语法为:
[修饰符] class 类名 extends 父类 implements 接口1,接口2…{
类体部分(如果继承了抽象类,需要实现继承的抽象方法;要实现接口中的抽象方法。)
}
注意:
如果要继承父类,继承父类必须在实现接口之前(extends和implements关键字是不能调换的)。
UML简介
- UML概念
Unified Modeing Language(UML)又称统一建模语言或标准建模语言。是一个支持模型化和软件系统开发的图形化语言。为软件开发的所有阶段提供模型化和可视化支持。