本质:以类的方式组织代码,以对象的组织(封装)数据
三大特性:封装、继承、多态
静态方法
package OOP;
public class Demo02 {
//静态方法 static
public static void main(String[] args) {
Student.say();
}
//非静态方法
}
public class Student {
public static void say(){
System.out.println("Hello World");
}
}
非静态方法,需要实例化 学生这个类
package OOP;
public class Demo02 {
//静态方法 static
//非静态方法
public static void main(String[] args) {
Student student = new Student();
student.say();
}
}
Application.java
package OOP.demo05;
public class Application {
public static void main(String[] args) {
Student student =new Student();//实例化对象
Student xiaoming =new Student();
Student xiaohong =new Student();
xiaoming.name="小明";
xiaoming.age=18;
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
}
}
Student.java
package OOP.demo05;
//学生类
public class Student {
//属性:字段
String name;
int age;
//方法:函数
public void study(){
System.out.println(this.name+"正在学习");
}
}
构造器也叫构造方法
一个类即使什么都不写 也会存在一个方法(构造方法)
构造方法满足 1、与类名相同 2、无返回值
1、使用new关键字,必须要有构造器
2、构造器一般用于初始化值
白话:该露的露,该藏的藏
专业:我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
封装(数据的隐藏)
在定义一个对象的特性的时候,有必要决定这些特性的可见性,即哪些特性对外部是可见的,哪些特性用于表示内部状态。通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏
使用private 修饰需要封装的成员变量
private无法直接调用赋值
但可以用设置的公共方法对其进行操作
package OOP.demo06;
public class Student {
private String name;
private int age;
private int id;
private String sex;
//提供一些方法用于对这些私有属性进行操作
public String getName(){
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
赋值
package OOP.demo06;
public class Application {
public static void main(String[] args) {
Student xiaoming =new Student();
xiaoming.setName("小明");
System.out.println(xiaoming.getName());
}
}
还可以用alt+insert 快速设置属性的 Get set方法
1、提高程序的安全性,保护数据
2、隐藏代码的实现细节
3、统一接口
4、提高程序的可维护性
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模
为什么需要继承?继承的作用? 第一好处:继承的本质在于抽象。类是对对象的抽象,继承是对某一批类的抽象。
第二好处:为了提高代码的复用性。
extands的意思是“扩展”。子类是父类的扩展。
定义‘人’类
package OOP.Demo07;
public class Person {
String name;
int age;
}
继承
package OOP.Demo07;
public class Student extends Person{
}
其中 Person为父类 ,Student为子类(派生类)
这里只能继承公有的 属性,方法
在java中,所有的类,都默认直接或者间接继承Object类
java中只有单继承 没有多继承(一个儿子只能有一个爹,但一个爹可以有多个儿子)
不管是显式还是隐式的父类的构造器,super语句一定要出现在子类构造器中第一行代码。所以this和super不可能同时使用它们调用构造器的功能,因为它们都要出现在第一行代码位置。
【super使用的注意的地方】
【super 和 this 的区别】
条件
重写的语法
注:多态是方法的多态,属性没有多态性
s2
是父类Person
的引用,其创建了一个Student
类的实例,这里由于父类中没有eat()方法,所以s2.eat()是无法成功的。
当父类中有eat方法时,如果子类没有重写方法,则会调用父类中的方法,重写则调用子类的方法
但是也可以通过强制转换来执行eat方法
Application.java
package OOP.demo09;
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
// new Student();
// new Person();
//但可以指向的引用类型是不确定的
Student s1 =new Student();
//父类的引用指向子类的对象
Person s2 =new Student();
// 但是不可以用子类的引用指向父类的对象
// Student s3 =new Person();
Object s4 =new Student();
s1.run();
s2.run();
s1.eat();
// s2.eat();
((Student)s2).eat();
}
}
Student.java
package OOP.demo09;
public class Student extends Person {
//重写父类run方法
@Override
public void run() {
System.out.println("学生正在跑步");
}
public void eat(){
System.out.println("学生正在吃饭");
}
}
Person.java
package OOP.demo09;
public class Person {
public void run(){
System.out.println("run");
}
}
这里创建了三个类,父类Person 子类1 Student 子类2 Teacher
package OOP.demo10;
public class Application {
public static void main(String[] args) {
Object object =new Student();
//Object -> Person -> Student
//Object -> Person -> Teacher
//Object -> String
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 String);//false
System.out.println(object instanceof Teacher);//false
System.out.println("==================");
//Object -> Person -> Student
//Object -> Person -> Teacher
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 String); 编译报错
System.out.println(person instanceof Teacher);//false
System.out.println("==================");
//Object -> Person -> Student
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 String); 编译报错
// System.out.println(student instanceof Teacher); 编译报错
}
}
其中绿色的就是关系表,如果两者有关系(在一条关系链上) 那么就会返回true,
由于都是Student类的实例,则其主要关系链 就一定含有Student
true:二者在主要关系链上(**标粗绿色的**)
flase:二者不在主要关系链上,但存在另外的关系链(没有标粗绿色的)
编译报错:二者无关系链
public class Application {
public static void main(String[] args) {
// 高 低
Person student =new Student();
// student.go(); 无法执行
((Student)student).go(); //强制类型转换为Student类型
}
}
public class Student {
private static int age;//静态变量
private double score;//非静态变量
public static void main(String[] args) {
go();
//run(); 无法运行
}
public void run(){
go();
}
public static void go(){
System.out.println("go");
}
}
静态方法会与类一起加载,但非静态方法不会,所以 run();编译错误
非静态方法run 调用了静态方法 go
public class Person {
{
//代码快(匿名代码块)
System.out.println("匿名代码块");
}
static {
//静态代码块
System.out.println("静态代码块");
}
}
package OOP.demo11;
public class Person {
{
//代码快(匿名代码块)
System.out.println("匿名代码块");
}
static {
//静态代码块
System.out.println("静态代码块");
}
public Person() {
System.out.println("构造方法");
}
public static void main(String[] args) {
Person person = new Person();
}
}
输出
静态代码块
匿名代码块
构造方法
观察输出可以发现,先执行了静态代码块 然后执行匿名代码块 再执行构造方法
注:静态代码块只会执行一次
例子
package OOP.demo11;
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();
}
}
输出
静态代码块
匿名代码块
构造方法
=================
匿名代码块
构造方法
可以发现输出第二次构造方法时,没有执行静态代码块
静态代码块只会在第一次执行时最开始运行
如下代码
import java.lang.Math;
public class Test {
public static void main(String[] args) {
System.out.println(Math.random());
}
}
我希望直接使用 random() 而不用加上 Math.
则可以通过静态导入包实现
import static java.lang.Math.random;
public class Test {
public static void main(String[] args) {
System.out.println(random());
}
}
import static java.lang.Math.random; 就是静态导入包
public abstract class Action {
}
public abstract class Action {
//约束~有人帮我们实现
//abstract 抽象方法,只有方法名字,没有方法实现
public abstract void doSomething();
}
当我们设置了抽象方法后,使用另外一个类继承这个类时,则
必须重写抽象方法 或者将子类也设置为抽象类
用接口定义增删改查
public interface UserService {
//接口中所有定义都是抽象的 public abstract
void add();
void delete();
void update();
void query();
}
只写了接口,还需要一个类来实现接口里面的方法,这里用到关键字implements
package OOP.demo13;
//类可以实现接口 用implements关键字
//对比抽象类 单继承 extends
public class UserServiceImpl implements UserService {
@Override
public void add() {
}
@Override
public void delete() {
}
@Override
public void update() {
}
@Override
public void query() {
}
}
实现了接口的类,就要重写接口中的方法
除了UserService 接口
我们新建一个接口 取名TimeService
package OOP.demo13;
public interface TimeService {
void timer();
}
我们可以在一个类里面实现多个接口
只需要将多个接口用逗号分开 并实现其方法即可
例子:A类中再定义一个B类 (套娃)
package OOP.demo14;
public class Outer {
private int id ;
public void out(){
System.out.println("outer");
}
class Inner{
public void in(){
System.out.println("inner");
}
}
}
public class Application {
public static void main(String[] args) {
//new
Outer outer = new Outer();
//通过外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.in();
}
}
一个java类中可以有多个class类,但只能有一个public class