一、什么是对象
万物皆对象,对象是客观存在的事物。
二、类与对象
1)类是对象的抽象,是对象的模板,用来描述对象的行为和状态。因为类是抽象的,所以需要new实例化,实例化后会返回一个自己的对象。静态的为属性,动态的为方法。
2)对象是类的具体实例。比如创建了一个能吃能喝能叫的“狗”类,而每一只的狗都是一个对象。对象的创建必须使用new创建对象,构造器。
注意下列例子中main和Student在同一个包下,如果不在同一包下,要导入包且定义的属性name和age要在前加入修饰符public。对象是通过引用来操作的,栈存放引用,堆存放具体的对象。除了八大基本类型外都为引用类型。属性定义默认初始化:数字:0或0.0、Boolean:false、引用:null。
public class Student {
// 属性:字段
String name;
int age;
// 方法
public void study(){
System.out.println(this.name+"在学习");//this代表当前这个类
}
}
public static void main(String[] args){
Student xiaoming = new Student();//xiaoming是对象
Student lihua = new Student();
xiaoming.name = "小明";
xiaoming.age = 3;
lihua.name = "李华";
lihua.age = 3;
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
System.out.println(lihua.name);
System.out.println(lihua.age);
}
三、构造方法
1)构造方法
创建方式为:
修饰符 返回值类型 方法名(。。。){ 方法体 return 返回值;}
静态方法:用到修饰符static,可以直接在main函数调用。调用只和左边,定义的数据类型有关。
动态方法:需要先new实例化这个类,才能调用。对象类型 对象名 = 对象值;虽然比静态方法麻烦,但是真正面向对象开发都是采用动态方法。
public static void main(String[] args){
Student.say();
Student student = new Student();//实例化Student类
student.eat();//调用动态方法
}
public class Student{
public static void say(){
System.out.println("说话");
}//静态方法
public void eat(){
System.out.println("吃");
}//动态方法
}
2)构造器
构造器与类名相同,没有返回值。使用new关键字就必须要有构造器,new的本质就是在调用构造器。我们创建对象就是在调用构造器。构造器的作用就是在创建对象并初始化对象的数据。
无参构造:一个类即使什么都不写,也会默认存在一个方法(构造器),与类名相同但没有返回值。
public Person(){
}
有参构造:一旦定义了有参结构,无参就必须显示定义,即如下在构造前放一个无参构造。
构造的重载与方法的重载同,构造名相同,参数(数量,类型等)不同。
public class Person{
String name;
int age;
public Person(){
this.name = "xxx";
}//无参,可以在里面初始化一些信息
public Person(String name){
this.name = name;
}
public Person(String name,int age){
this.name = name;
this.age = age;
}
}
public static void main(String[] args) {
//new 实例化了一个对象
Person person = new Person();
System.out.println(person.name);//xxx 没定义初始值就是null
}
四、封装
封装主要针对属性,很少针对方法。通过修饰符private进行私有化,进行私有化后,通过get来获得数据,通过set来给这个数据设置值,在设置值时也能增加一些条件语句来进行不同设置。
public class Student {
private String name;
private int age;
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age > 120 || age<0){
age = 0;//不合法
}else {
this.age = age;
}
}
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("二蛋");
//不能直接s1.name = "";
System.out.println(s1.getName());
s1.setAge(999);//不合法的数据 可以在程序里规避掉
System.out.println(s1.getAge());
}
}
五、继承
在Java中所有的类都默认直接或间接继承Object。子类使用extends来继承父类,继承后可以使用父类的方法。继承只允许单继承
六、重写
重写:需要有继承关系,子类重写父类的方法,方法名必须相同,参数列表必须相同,修饰符范围可以扩大但不能缩小:public > protected > default > private,排除的异常范围可以缩小,但不能扩大。重写子类的方法和父类必须要一致,仅方法体不同。因为父类的功能,子类不一定需要或不一定满足,所以需要重写。
重写用super调用父类的构造方法,super调用父类的构造方法必须在构造方法的第一个,只能出现在子类的方法或者构造方法中,super和this不能同时调用构造方法。this代表本身调用者这个对象,没有继承也可以使用,super代表父类对象的应用,只有在继承条件在才可以使用。
public class Person {
private int money = 90_0000_0000;//私有的钱
public void say(){
System.out.println("说了一句话");
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public Person() {
System.out.println("Person无参构造执行了");
}
protected String name = "erdan";
public void print(){
System.out.println("Person");
}
public class Student extends Person{
public Student() {
super();//隐藏代码:调用了父类的无参构造
//调用父类的构造器,必须要在子类构造器的第一行
System.out.println("Student无参构造执行了");
}
private String name = "erdan2";
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);//erdan2
System.out.println(super.name);//父类里的erdan
}
}
public static void main(String[] args) {
Student student = new Student();
Person s2 = new Student();
student.say();
System.out.println(student.getMoney());
student.test("二蛋");
student.test1();
}//输出了:Person无参构造执行了
//Student无参构造执行了
//说了一句话
//9000000000
//二蛋
//erdan2
//erdan
//Student
//Student
//Person
七、多态
多态:同一个方法可以根据发送对象的不同采用多种不同的行为方式。多态是方法的多态,属性没有多态,方法要有联系,比如父类和子类。拥有继承关系,方法需要重写,父类的引用指向子类对象时存在多态。是否存在关系可以通过instanceof来判断。
子类的实际类型是确定的,但可以指向的引用类型就不确定了:父类的引用指向子类,但不能调用子类独有的方法。对象能执行哪些方法主要看对象左边的类型,和右边的关系不大。
public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
public class Person {
public void run(){
System.out.println("Person");
}
}
Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();
((Student) s2).eat();//子类重写了父类的方法,执行子类的方法
s1.eat();
System.out.println(X instanceof Y);能不能编译通过(存在父子关系才行)
八、抽象类
通常用abstract来实现抽象。抽象方法只有方法名字,没有方法的实现,不能new这个对象类,只能靠子类去实现它,抽象方法必须写在抽象类中,抽象类可以写在普通的方法。虽然不能new但是也存在构造器,即使没有提供任何构造函数,编译器将抽象类添加默认的无参数的构造函数,如果没有构造器的话子类将无法进行编译。抽象类是一种约束,先定义了需要的抽象类,具体的实现可以又他人替代完成。抽象类的所有方法,继承他的子类都必须要实现。
public abstract class Action {
public abstract void doSomething();
}
public class A extends Action{
@Override
public void doSomething() {
}
}
九、接口
接口也是一种约束,定义一些方法,让不同的人实现,接口不能被实例化,也没有构造方法,implements可以实现多个接口,接口中的方法必须被重写。
public class UserServiceImpl implements UserService,TimeService{
@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 timer() {
}
}
public interface UserService {
//常量 public static final 不过一般不把常量定义在接口
int AGE = 99;
//接口中的所有定义其实都是抽象的 public abstract 可以不写
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
public interface TimeService {
void timer();
}
十、内部类
一个Java类中可以有多个class类,但只能有一个public外部类。写在一个类中的另一个类称为内部类。
1)局部内部类
public class Outer {
//外部类
private int id = 10;
public void out(){
System.out.println("这是外部类的方法");
}
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
//获得外部类的私有属性
public void getID(){
System.out.println(id);
}
}
//局部内部类
public void method(){
class Inner2{
public void in2(){
}
}
}
}
2)匿名内部类
没有名字初始化类,不用将实例保存到变量中。
public class Test {
public static void main(String[] args) {
new Test(){
public void say(){
System.out.println("我是匿名内部类");
}
}.say();
new Apple().eat();
}
}
class Apple{
public void eat(){
System.out.println("1");
}