面向对象的三大基本特征
封装
封装就是隐藏类的各种信息,不允许外部直接访问。只能通过给定公开的方法访问数据,对数据私有化,让外部不能看到里面是如何运行的,提高安全性。
代码展示:
public class Address {
//私有化各项属性
private String State;
private String City;
private String Country;
private String Street;
private String Postal_Code;
//提供让外部能够获取操作数据的get/set方法
public String getState() {
return State;
}
public void setState(String state) {
State = state;
}
public String getCity() {
return City;
}
public void setCity(String city) {
City = city;
}
public String getCountry() {
return Country;
}
public void setCountry(String country) {
Country = country;
}
public String getStreet() {
return Street;
}
public void setStreet(String street) {
Street = street;
}
public String getPostal_Code() {
return Postal_Code;
}
public void setPostal_Code(String postal_Code) {
Postal_Code = postal_Code;
}
//公开的方法
public void Validate(){
};
public void OutputAsLabel(){
};
}
访问控制符
private修饰的成员变量和方法仅仅只能在本类中调用,因此private修饰的内容是对内实现数据的封装,如果“公开”会增加维护的成本。
public修饰的成员变量和方法可以在任何地方调用,因此public修饰的内容是对外可以被调用的功能。在定义类的时候,一般采用成员变量私有化,方法公开的原则。
protected修饰的成员变量和方法可以被子类及同一个包中的类使用。
默认访问控制即不书写任何访问控制符,默认访问控制的成员变量和方法可以被同一个包中的类调用。
继承
继承的叫子类,被继承的叫父类。继承就是让子类可以拿到父类公开的属性和方法,减少代码的冗余提高复用率。
代码展示:
public class Animal {
String color;//颜色
Date birth;//生日
String sex;//性别
int count;//脚的数量
public void sing(String sing){
System.out.println("唱:"+sing);
}
public void eat(String food){
System.out.println("吃:"+food);
}
public void run(){
System.out.println("到处跑");
}
}
//Chicken 继承了Animal中的所有成员变量和成员方法,同时有自己独有的fly方法
class Chicken extends Animal{
public void fly(){
System.out.println("飞.....");
}
}
//Dog 继承了Animal中的所有成员变量和成员方法,同时有自己独有的方法WatchGate
class Dog extends Animal{
public void WatchGate(){
System.out.println("看家护院.....");
}
}
多态
多态就是同一个引用用不同种类的参数实现不同的操作
代码展示:
public class Shape {
//方法
//计算面积
//方法的重载:方法的修饰符。返回值,名字都一样,但是方法的参数不同(可以是类型不同,也可以是个数不同)
// 方法签名: 方法的修饰符,方法的名字,方法的参数这个整体
public double area(int r) { //圆形的面积 int类型的参数
double a = 3.14 * r * r;
return a;
}
public double area(double w, double h) { //长方形的面积 double类型的参数
double a = w * h;
return a;
}
public double area(int bottom, double h) {//三角形的面积 int和double类型的参数
double a = bottom * h / 2;
return a;
}
}
public class Printer {
public static void main(String[] args) {
//多态
//方法的重写
Printer p = new Printer3D();
Printer p1 = new PrinterBlack();
Printer p2 = new PrinterColor();
p.print();
p1.print();
p2.print();
}
public void print() {
System.out.println("打印机可以打印");
}
}
class Printer3D extends Printer {
@Override
public void print() {
System.out.println("3D打印机》》》》》》");
}
}
class PrinterBlack extends Printer {
@Override
public void print() {
System.out.println("黑白打印机。。。。。。。。。。。。。。");
}
}
class PrinterColor extends Printer {
@Override
public void print() {
System.out.println("彩色打印机。。。。。。。。。。。。。。");
}
}
关键字
package
定义类的时候需要指定类的名称。但是如果仅仅将类名作为类的唯一标志,则会出现命名冲突的问
题。
在java中,是用package 来解决命名冲突的问题。因此定义类的时候,一般需要先给类指定一个包
名。
类的真实名字是: 包名 + 类名。
import
如果要在程序中,使用某个类,可以用该类的全名,这样比较复制。
java.util.Date date = new java.util.Date();
一般使用import 语句导入这个类,然后使用该类。
public
public修饰的成员变量和方法可以在任何地方调用,属于公开的。
void
void表示设置的方法无返回值。
static
修饰成员变量:
用static修饰的成员变量不属于对象的数据结构。
static修饰的变量属于类的变量,通常可以通过类名来引用static成员。
static成员变量和类的信息一起存储在方法区,而不是在堆内存中。
一个类的静态成员变量只有一份,而非静态成员对象有多份,即每个对象都有自己的非静态成员变量。
修饰成员方法:
类中的方法,通常都会涉及到堆具体对象的操作,这些方法在调用时,需要隐式的传递对象的引
用。
static修饰的方法则不需要针对对象进行操作,其运行结构仅仅与输入的参数有关系。调用时候直接通过类名引用。
static修饰的方法是属于类的方法,通常用于提供工厂方法,或者工具方法。
static修饰的方法,调用的时候没有具体的对象,因此static修饰的方法不能调用非静态成员变量和成员方法。
public class TestDog {
public static void main(String[] args) {
//1.创建对象
Dog dog1 = new Dog();
Dog dog2 = new Dog();
//2.给属性赋值
dog1.name = "布多";
dog2.name = "小黑";
dog1.sex = "女";
dog2.sex = "男";
dog1.kind = "拉布拉多";
dog2.kind = "德牧";
dog1.color = "褐棕";
dog2.color = "黑色";
dog1.age = 3;
dog2.age = 4;
//3.调用方法
dog1.run();
dog1.kings("拉布拉多");
dog2.kings("德牧");
}
}
abstract
用abstract关键字修饰的类称之为抽象类。
抽象类不能实例化,抽象类的意义在于“被继承”。
抽象类为子类“抽象”出公共部分,通常也定义了子类所必须实现的抽象方法。
一个抽象类可以有抽象方法,也可以有非抽象方法。
一个类继承了抽象类,那么必须实现父类的抽象方法,除非该类依然定义为抽象类。
public abstract class Person {//规定了子类必须的重写尔eat,sleep两个方法
String id;
Date birth;
public abstract void eat(String food);
public abstract void sleep();
}
extends
extends关键字可以实现类的继承。
子类(sub class) 可以继承父类(super class)的成员变量及成员方法。同时也可以定义自己的成员变量和成员方法。
java语言不支持多继承,一个类只能继承一个父类。 但一个父类可以有多个子类。
class Police extends Person {
String tel;
@Override// 重写(@+类型,就叫注解),保证子类中的方法签名和父类的整个方法的方法签名完全一样
public void eat(String food) {
System.out.println("food = " + food);
}
@Override
public void sleep() {
System.out.println("24小时不睡");
}
public void catchBadPerson() {
System.out.println("正在抓坏人");
}
}
class Doctor extends Person {
String level;
@Override
public void eat(String food) {
System.out.println("Food:" + food);
}
@Override
public void sleep() {
System.out.println("通宵手术");
}
}
final
修饰类:
final关键字修饰的类不可以被继承。
对于一些类,设置了final修饰,可以避免滥用继承造成的危害。
修饰成员变量:
final修饰成员变量,意为不可以改变。
该成员变量需要在初始化的时候赋值,对象一旦创建,即该值不可以改变。
修饰成员方法:
final关键字修饰的方法可以不被重写。
防止子类在定义自己的方法的时候,不经意被重写。
class Boo {
public final void print() { //final修饰的方法,不能被重写
System.out.println("我是Boo中的print方法");
}
}
class Coo extends Boo {
int count;
final int size = 100;// final修饰的变量,定义的时候就赋值,赋值之后,值不可以变
//size=120;//编译错误: final修饰的成员变量的值不可以修改了
//定义常量:①用static和final一起修饰[static让这个常量可以通过类名调用。final让这个变量的值不变,那就是常量了]
// ②建议常量的命名名字全大写。
static final double PI = 3.14;
//练习: 最大年龄120.最小年龄0
static final int MAX_AGE = 120;
static final int MIN_AGE = 0;
/*public void print(){// 编译错误:父类中的print方法,是final修饰的,不能被重写
}*/
}
super
指代父类,可以通过super()的方式调用父类的构造函数,super. 方法的方式调用父类的方法。
overwrite
子类从父类继承的方法,如果不能满足子类的需要,可以重写父类的方法。即方法名和参数列表和父类保持完全一致,方法的实现不同。
子类重写父类的方法之后,子类对象优先调用自己的方法。
子类重写父类的方法的时候,可以在重写的方法中,使用super关键字调用到父类的方法。
interface
接口可以看成是特殊的抽象类。
接口中只能定义常量和抽象方法。
一个类可以实现多个接口,多个接口之间用逗号分隔。这个类需要实现所有接口的抽象方法。
接口可以作为一种类型声明变量,一个接口类的变量可以引用实现了该类的对象。通过该引用,调用接口中的方法(实现类中提供了接口方法的实现)。
接口间可以存在继承关系,一个接口可以通过extends关键字继承另外一个接口。
子接口继承了父接口中定义的所有方法。
public interface Animal {
//定义常量
static final String Ancestors = "女娲";
//定义抽象方法
void eat();//接口中的方法默认是public abstract.所以可以省略这两个关键字
public abstract void sleep();
public abstract void sing();
}
implements
一个类实现一个或多个接口,支持多实现。
//Cat实现了Animal接口,所以Cat是Animal的子类
class Cat implements Animal{//类需要实现接口中的所有抽象方法,否则把类设置为abstract类
String brand;
String name;
@Override
public void eat() {
System.out.println("吃东西");
}
@Override
public void sleep() {
System.out.println("睡觉");
}
@Override
public void sing() {
System.out.println("喵喵喵");
}
public void catchMouse(){
System.out.println("抓老鼠");
}
}
instanceof
对于一个父类的引用类型,可以指向该类的对象也可以指向其任意一个子类型的对象。
通过instanceof 关键字判断引用指向的对象的实际类型。
根据引用指向的实际类型,将引用强制转换为实际类型。
public class TestAnimal {
public static void main(String[] args) {
Animal a1 = new Animal();
Animal a2 = new Dog(); //Dog和chicken都是Animal的子类
Animal a3 = new Chicken();
//5.类型转换:
//instanceof:用于判断 引用 对应的对象是否为某种类型,是结果为true,否则结果为false.
//a2是动物, 但是a2本质是狗. a2不能转换为鸡这个类型
if (a2 instanceof Dog) { //instanceof的运算结果是true或者false
//a2是Dog,那就可以把a2转换为Dog,然后赋值给Dog类型的引用
Dog dog1 = (Dog) a2;
dog1.WatchGate();//类型转换之后,就可以调用子类Dog的所有方法
}
if (a3 instanceof Chicken) {
Chicken chicken = (Chicken) a3;
chicken.fly();
}
//Chicken chicken = (Chicken) a2;
//没有编译错误,有运行错误:ClassCastException - 类型转换错误
/*Exception in thread "main" java.lang.ClassCastException: day2.Dog cannot be cast to day2.Chicken
at day2.TestAnimal.main(TestAnimal.java:18)*/
}
this
在方法中可以通过this关键字表示调用该方法的对象。(一般用this.来调用)
通常在类中使用this区分成员变量和参数,如果没有歧义,可以省略this。
null
引用类型变量用于存放对象的地址,可以给引用类型赋值为null,表示不指向任何对象。
如果某个引用类型变量为null的时候,不能访问对象,否则抛出空指针异常。
public class Student {
//成员变量
String name;
String sex;
int score;
Date birth;
//方法
public void show() {
System.out.println(this.name + ":" + this.sex + ":" + this.score + ":" + this.birth);
System.out.println(name + ":" + sex + ":" + score + ":" + birth);
}
}
public class TestStudent {
public static void main(String[] args) {
Student stu = null; //stu的初始数据值是null
System.out.println(stu);
//stu.show();输出学生信息。 因为stu是null,null声明都没有,所以程序抛异常:java.lang.NullPointerException
stu = new Student();//stu中保存的就是student对象的内存地址
System.out.println(stu);//day1.Student@1b6d3586 -- 包名.类名 @ 16进制的整数
}
}
equals
equals是父类Object中提供的的一个equals方法,用于制定两个对象是否相等的比较规则。
Object中的equals默认是比较两个对象的地址是否相同。
子类重写父类的equals方法,自定义比较规则:
比如: 判断两个点是否相同,可以判断两个点的x位置和y位置同时相等,则两个点相同。
如果两个对象比较equals为true ,那么这依然不能说明是否为同一个对象。
== 和equals的区别
== :用于判断基本数据类型的数据值是否相等,
用于判断引用类型的地址是否相等(如果引用地址相等,说明一定是指向的同一个对象,否则,说明是指向不同的对象)
equals: 类中的方法,用于判断对象的内容是否相等
public class EqualsDemo {
public static void main(String[] args) {
int a = 10;
int b = 10;
System.out.println(a == b);//true.
Point p1 = new Point();
p1.x = 10;
p1.y = 10;
Point p2 = new Point();
p2.x = 10;
p2.y = 10;
System.out.println("p1 = " + p1);
System.out.println("p2 = " + p2);
System.out.println(p1 == p2);//== — 用于判断引用类型地址是否相等,false
Student stu1 = new Student("1001", "小米", "java2202");
Student stu2 = new Student("1001", "小米", "java2202");
System.out.println("stu1 : " + stu1);
System.out.println("stu2 : " + stu2);
System.out.println(stu1 == stu2);//false
Student stu3 = stu1;
System.out.println(stu3 == stu1);//如果两个引用使用==判断,结果为true,说明这是引用的同一个对象
// ***如果规定 Point类型:如果x,y和另一个对象的x,y相等,我们就认为这两个点是同一个点
// 如果规定Student类型,code,name,className各自相等,就认为是同一个学生
// ** 如果没有重写equals方法
//System.out.println(p1.equals(p2));//false ** Object中定义的equals方法,就是用==判断两个对象的地址是否相等
// ** 如果重写了equals方法
System.out.println(p1.equals(p2));//true
Point p3 = new Point();
p3.x=10;p3.y=5;
System.out.println(p1.equals(p3));//false. 因为x和y没有同时相等。所以equals方法,返回false
System.out.println(p1.equals(null));//false. 空不能和任何对象相比
System.out.println(p1.equals(stu3));//false. 不同类型,不能比
System.out.println(p1.equals(p1));//true ,自己和自己相等
}
}
return
java中规定方法必须要指定返回值类型,如果没有返回值类型,可以使用void关键字。
java中使用return关键字,在方法的内部返回数据。
常与void作比较,void表示设置的方法无返回值
错题总结
1.对于构造方法,描述错误的是()C B
A:构造方法时类中的一种特殊方法,其名称必须与类名相同
B:构造方法的返回值类型是void
C:构造方法的作用主要用于初始化实例对象
D:创建对象时会自动调用构造方法
8.给定java代码如下,编译运行,结果是( D A )
public static void main (String[] args) {
int i; // 没有初始化
System.out.println ("i="+i);
}
[A] 编译错误 [B] 运行时出现异常
[C] 正常运行,输出i=-1 [D]正常运行,输出i=0
14.以下语句在编译时不会出现警告或错误的是( A C )
[A] float f=3.14; [B]char c="c";
[C] Boolean b=null; [D]int i=10.0;
// Boolean是java提供的方法
16.给出下面代码, 那个语句是正确的?(D A )
publicclass Person{
intarr[] = new int[10];
publicstatic void main(String a[]) {
System.out.println(arr[1]);
}
}
[A] 编译时将产生错误; [B] 编译时正确,运行时将产生错误;
[C] 输出零; [D] 输出空;
18.设有下面的两个类定义, 则顺序执行如下语句后输出结果为( A D )
class AA {
void Show(){ System.out.println(“我喜欢Java!”);
}
class BB extends AA {
void Show(){ System.out.println(“我喜欢C++!”);}
publicstatic void main(String[] args) {
AA a = (AA)new BB(); // 运行时仍视为BB()方法
BB b = new BB();
a.Show();
b.Show();
}
}
[A] 我喜欢Java!
我喜欢C++!
[B] 我喜欢C++!
我喜欢Java!
[C] 我喜欢Java!
我喜欢Java!
[D] 我喜欢C++!
我喜欢C++!
19.下列说法正确的是 (D A )
[A]能被java.exe成功运行的javaclass文件必须有main()方法
[B] Java源码编译完生成平台直接可运行的二进制文件
[C] Java源码直接运行在JVM中,JVM会对源码进行编译和运行
[D] class文件是字节码,字节码是和机器相关的可运行代码
20.下面关于Java接口的说法错误的是( B C )。
[A] 一个Java接口是一些方法特征的集合,但没有方法的实现
[B] Java接口中定义的方法在不同的地方被实现,可以具有完全不同的行为
[C] Java接口中可以声明私有成员
[D] Java接口不能被实例化
25.给定如下Java代码,编译时会在( A D )出现错误。
class Parent{
}
class Child extends Parent{
public static void main(String[] args){
Parent p1=new Child();//第一行 向上造型
Parent p2=new Parent ();//第二行
Child c1=new Child();//第三行
Child c2=new Parent();//第四行
}
}
(A) 第一行
(B) 第二行
(C) 第三行
(D) 第四行
总结
本阶段的学习让我整体理解了什么是面向对象,以前对封装继承多态什么的只是说的出来名字,现在可以具体的说明是什么了。
但是对于细节上的知识点还需要多加记忆,曾经只是照着代码敲有过照面,现在需要转化成自己的东西。