Java三大特征:封装、继承、多态
封装
高内聚,低耦合:类的内部数据数据操作自己完成,不允许外部干涉;尽量暴露少量方法给外部使用
属性私有,get/set
封装的意义:
1、提高程序的安全性,保护数据
2、隐藏代码的实现细节
3、统一接口
4、系统的可维护性增加
Student类:
package oop.Demo03;
//类
//封装一般是对于属性来的,很少封装方法
//private:私有
public class Student {
//属性私有
private String name;//名字
private int id;//学号
private char sex;//性别
private int age;
//提供一些可以操作这些属性的方法,提供一些public的get、set方法
//get 获得这个数据 (驼峰命名)
public String getName(){
return this.name;
}
//set 给这个数据设置值
public void setName(String name){
this.name=name;
}
public void setAge(int age){//定义合理性
if(age>120||age<0)
this.age=3;
else{
this.age=age;
}
}
public int getAge(){
return this.age;
}
//学习()
//睡觉()
}
Application类:
package oop;
import oop.Demo03.Student;
public class Application {
public static void main(String[] args) {
Student s1=new Student();
// s1.name = 不再能通过.操作符直接使用这些属性
s1.setName("张三");
System.out.println(s1.getName());//张三
s1.setAge(999);
System.out.println(s1.getAge());//3
}
}
继承
-
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模
-
关键字:extends——扩展,子类(派生类)是父类的继承(基类),子类和父类之间从意义上将具有”is a“的关系
-
Java中只有单继承没有多继承,一个儿子只有一个爸爸,一个爸爸可以有多个儿子
-
除继承以外,类与类之间的关系还有依赖、组合、聚合等
子类继承了父类就会拥有父类的全部方法!(public)
私有的东西(private)无法被继承
在java中,所有的类都默认直接或者间接地继承object类
super注意点:
super();
1、super调用父类的构造方法,必须在构造方法的第一个
2、super只能和初夏安在子类的方法或者构造方法中
3、super和this不能同时调用构造方法
super和this的区别
this("hello");
代表的对象不同:
this:本身调用这个函数
super: 代表父类对象的引用
前提不同:
this:没有继承也可以使用
super:只能在继承条件下才可以使用
构造方法不同:
this():本类的构造
super():父类的构造
父类:
package oop.Demo04;
// 人 :父类
//public
//protected
//default 默认
//private
public class Person {
public Person(){
System.out.println("Person无参执行了");
}
protected String name="zhangsan";
public void print(){
System.out.println("Person");
}
}
子类:
package oop.Demo04;
//学生 is 人 :派生类、子类
public class Student extends Person{
public Student(){
//隐藏代码:调用了父类的无参构造:super();
super();//调用父类的构造器,必须在子类构造器的第一行
//this("hello");
System.out.println("Student无参构造执行了");
}
public Student(String name) {
this.name=name;
}
private String name="zhangwu";
public void print(){
System.out.println("Student");
}
public void test1(){
print();//Student
this.print();//Student
super.print();//Person
}
public void test(String name){
System.out.println(name);//张五
System.out.println(this.name);//zhangwu
System.out.println(super.name);//父类中的zhangsan
}
}
应用:
package oop;
import oop.Demo04.Person;
import oop.Demo04.Student;
public class Application {
public static void main(String[] args) {
Student student=new Student();
// student.test("张五");
// student.test1();
// Student s1=new Student();
// s1.say();//说了一句话
// //System.out.println(s1.money);//报错
// Person person=new Person();
}
}
方法重写:(多态)
重写都是方法的重写,与属性无关
父类:
package oop.Demo04;
//重写都是方法的重写,与属性无关
public class B {
public void test(){
System.out.println("B=>test()");
}
}
子类:
package oop.Demo04;
public class A extends B{
public void test(){
//super.test();
System.out.println("A=>test()");
}
}
应用:
package oop;
import oop.Demo04.B;
import oop.Demo04.A;
public class Application {
public static void main(String[] args) {
//方法的调用之和左边,定义的数据类型有关
A a = new A();
a.test();//A
//父类的引用(b)指向了子类(A)
B b = new A();//子类重写了父类的方法
b.test();//A
}
}
结果:
静态方法和非静态方法区别很大:
如果方法改成静态的:(就不是重写了)
package oop.Demo04;
//重写都是方法的重写,与属性无关
public class B {
public static void test(){
System.out.println("B=>test()");
}
}
package oop.Demo04;
public class A extends B{
public static void test(){
//super.test();
System.out.println("A=>test()");
}
}
package oop;
import oop.Demo04.B;
import oop.Demo04.A;
public class Application {
public static void main(String[] args) {
//方法的调用之和左边,定义的数据类型有关
A a = new A();
a.test();//A
//父类的引用(b)指向了子类(A)
B b = new A();//子类重写了父类的方法
b.test();//B
}
}
结果:
是不是重写可以看左边蓝色圆圈箭头,是重写才有,静态方法没有,改成私有也没有:
改成私有:
总结:
重写需要有继承关系,而且是子类重写父类的方法!
1、方法名必须相同
2、参数列表必须相同(区分于重载,重载是当前方法,且参数列表不同)
3、修饰符:范围可以扩大,但不能缩小 public>protected>default>private
4、区分于抛出异常:范围可以被缩小,但不能扩大。 ClassNotFoundExcetion -->Excetion(大)
重写就是子类的方法和父类必须相同,方法体不同
为什么要重写:
1、父类的功能,子类不一定需要,或者不一定满足
快捷键:Alt+Insert : override
面向对象基础
关键字 ( instanceof )
instanceof (类型转换) 引用类型,判断一个对象是什么类型
父类:
package oop.Demo04;
public class Person {
}
子类1:
package oop.Demo04;
public class Student extends Person{
}
子类2:
package oop.Demo04;
public class Teacher extends Person{
}
应用:
package oop;
import oop.Demo04.*;
public class Application {
public static void main(String[] args) {
//Object>String
//Object>Person>Teacher
//Object>Person>Student
Object object = new Student();
//System.out.println(X instanceof Y);//能不能编译成功,取决于X与Y有没有父子关系!
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Teacher);//false
System.out.println(object instanceof String);//false
System.out.println("================");
Person person = new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
System.out.println(person instanceof Teacher);//false
// System.out.println(person instanceof String);//编译报错,平级不能比较
System.out.println("================");
Student student = new Student();
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Object);//true
// System.out.println(student instanceof Teacher);//编译报错,平级不能比较
}
}
类型之间的转化:父|子
1、父类引用指向子类对象
2、把子类转换为父类(向上转型,低转高),直接转
3、把父类转换为子类(向下转型,高转低),需要强制转换
4、方便方法的调用,减少重复代码
抽象的编程思想:封装、继承、多态!抽象类:接口
父子关系和上文一样:
package oop;
import oop.Demo04.*;
public class Application {
public static void main(String[] args) {
//类型之间的转化:父|子
//高 低
Person obj = new Student();
// student.go();//不能执行
//student将这个对象转换为Student类型,就可以使用Student类型的方法了
//高转低强制转换
Student student = (Student) obj;
student.go();
((Student) obj).go();
//子类转为父类,可能丢失自己本来的一些方法
Student student1 = new Student();
student1.go();
Person person = student;//低转高直接转换
}
}
关键字 static(静态)
对类来说静态变量在内存中只有一个,它能被类的所有实例共享
在类中,静态方法可以直接调用静态方法,但不能调用非静态方法
非静态方法可以调用静态方法里的所有东西
package oop.Demo05;
//static
public class Student {
private static int age;//静态变量,多线程会使用
private double score;//非静态变量
public void run(){
go();//非静态方法可以调用静态方法里的所有东西
}
public static void go(){
}
public static void main(String[] args) {
Student s1= new Student();//对类来说静态变量在内存中只有一个,它能被类的所有实例共享
System.out.println(Student.age);//0//静态变量推荐使用类名访问
// System.out.println(Student.score);//无法编译,非静态字段不能这么用
System.out.println(s1.age);//0
System.out.println(s1.score);//0.0
Student.go();
go();//在类中,静态方法可以直接调用静态方法,但不能调用非静态方法
// Student.run();//编译不成功
}
}
静态代码块:
package oop.Demo05;
public class Person {
{
//代码块(匿名代码块),作用:赋初始值
//没有名字,无法调用,类加载一次运行一次
System.out.println("匿名代码块");
}
static{
System.out.println("静态代码块");
//静态代码块,类一加载直接执行,永久只执行一次
}
public Person() {
System.out.println("构造方法");
}
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("=============");
Person person2 = new Person();
}
}
结果:
被final修饰的类不能被继承:
public final class Person {
}
public class Student extends Person{
}
抽象类(abstract)
关键字:abstract
public abstract class Action
抽象的抽象:约束
抽象类的所有方法,由继承了它的子类,都必须实现它的方法
抽象类的特点:
1、不能new这个抽象类,只能靠子类去实现它:约束
2、有抽象方法的类一定是抽象类,但抽象类里可以写普通方法
抽象类不能new,那它有构造器吗?
抽象类存在的意义是什么?
比如创建游戏中的角色,每个角色非常复杂,反复创建非常麻烦,抽象共有属性,修改各自方法就行。可以节省代码,提高效率
抽象类:
package oop.Demo06;
//abstract 抽象类:类 只能单继承 extends:单继承(只能继承一个类) 接口可以实现多继承
public abstract class Action {
//约束:有人帮我们实现
//abstract 抽象方法,只有方法名字,没有实现
public abstract void doSomething();
public void hello(){
System.out.println("hello");
}
}
抽象类的子类:
package oop.Demo06;
//抽象类的所有方法,由继承了它的子类,都必须实现它的方法
public class A extends Action{
@Override
public void doSomething() {
}
}
接口(interface)
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有!
接口:只有规范!自己无法写方法。专业的约束!约束和实现分离:面向接口编程
接口就是规范,定义的是一组规则,本质是契约
关键字:interface
public interface UserService
软件IDEA中普通类、抽象类和接口在图标上的的区别:
接口的作用:
1、是一种约束,可以定义一些方法,让不同的人实现
2、接口中的所有方法都是 public abstract,所有属性都是public static final
3、接口不能被实例化,接口不是类,接口中没有构造方法
4、类可以实现接口 关键字:implements 接口(可以实现伪多继承)
5、实现了接口的类,就需要重写接口中的所有方法
接口1:
package oop.Demo07;
//interface 定义的关键字,接口都需要有实现类
public interface UserService {
//接口中的所有定义的方法其实都是抽象的public abstract
public abstract void run();
//接口中的所有定义的属性都是常量public static final(一般不会在接口里定义常量)
public static final int age = 99;
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
接口2:
package oop.Demo07;
public interface TimeService {
void time();
}
应用1:
package oop.Demo07;
//抽象类:extends
//类可以实现接口 关键字:implements 接口
//实现了接口的类,就需要重写接口中的方法
//多继承:利用接口实现多继承
public class UserServiceImpl implements UserService,TimeService{
@Override
public void run() {
}
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void time() {
}
}
内部类
在A类中定义B类,B类相对于A类就是内部类
使用:通过外部类来实例化内部类
一个java文件中可以有多个class类,但只能有一个public class
例1:
内部类:
package oop.Demo08;
public class Outer {
private int id;
public void out() {
System.out.println("这是外部类的方法");
}
public void method(){
class Inner2{//局部内部类,类似函数里的局部变量
public void in(){//内部类里的方法
}
}
}
public class Inner {//如果这里是public static class
// 那下面getID就不行了,除非把id也改成static
public void in() {
System.out.println("这是内部类的方法");
}
//内部类可以 获得外部类的私有属性
public void getID() {
System.out.println(id);
}
}
}
应用:
package oop;
import oop.Demo04.*;
import oop.Demo08.Outer;
public class Application {
public static void main(String[] args) {
//new
Outer outer = new Outer();
//通过外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.in();
}
}
例2:
(一般不这么用)
package oop.Demo08;
public class Test {
public static void main(String[] args) {
Apple apple = new Apple();
//没有名字初始化类——匿名对象的使用,不用将实例保存到变量中
new Apple().eat();
UserService userService = new UserService(){
public void hello(){
}
};
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
interface UserService{//接口
void hello();
}