面向对象和面向过程
这是一个抽象的概念。
面向对象的世界里,一切都是对象。
比如我们去买菜的话,需要去确定买什么菜,买多少的菜,然后去菜市场购买。只是我自己至始至终的去完成一件事情,就被称为面向过程,而面向对象中。可能是我让弟弟妹妹去买菜,老板给弟弟妹妹菜,然后菜就到了我的手里。面向对象的几个对象(妹妹,弟弟,老板,菜)相互交互作用后,事情就做好了。
对象需要类,有了类我们就有了对象,对象之间可以交互,就可以面向对象
类
定义一个类:
class WashMachine{
//WashMachine就是洗衣机这一个类,标准采用大驼峰去书写。
//类里包括两个对象,成员对象(字段/属性)和成员方法(行为)
//成员变量定义到类的内部,行为的外部。
pubic String brand;
public String type;
public double height;
//以上就是洗衣机的属性。
public void WashClother(){
System.out.println("洗衣功能");
}
public void DryClother(){
System.out.println("脱水功能");
}
//以上就是洗衣机的行为。
}
实例化
定义了一个类,就是定义了一个新的类型,和int,double相似。
class Dog{
public String name;
public int height;
public void Bark(){
System.out.println("汪汪汪");
}
}
public class L513 {
public static void main(String[] args) {
//通过new关键字实例化了一个对象。来调用成员变量
Dog dog = new Dog();
System.out.println(dog.height);
System.out.println(dog.name);
}
}
dog会在栈上开辟一个空间,里面存放的是类的地址,地址里有成员变量和成员方法。
此时运行结果是0,因为成员变量会默认初始化。
成员变量 是引用数据类型是,初始化成null,是基本数据类型是,初始化成0。
基本数据类型中有两个例外,boolea对应的是false,char对应的是‘\u0000’
前面新定义了两个boole和char类型的成员变量进行打印。
调用方法同理
class Dog{
public String name;
public int height;
public void bark(){
System.out.println("汪汪汪");
}
}
public class L513 {
public static void main(String[] args) {
//通过new关键字实例化了一个对象。来调用成员变量
Dog dog = new Dog();
System.out.println(dog.height);
System.out.println(dog.name);
dog.bark();
}
}
在实例化对象后,可以在main函数内直接赋值。
dog.name = "王二狗";
dog.height=114514;
实例化可以实例化多个对象。
class Dog{
public String name;
public int height;
public boolean yea;
public char gushujisama;
public void Bark(){
System.out.println("汪汪汪");
}
}
class Dog2{
public String name;
public int height;
public boolean yea;
public char gushujisama;
public void Bark(){
System.out.println("喵喵喵");
}
}
public class L513 {
public static void main(String[] args) {
//通过new关键字实例化了一个对象。
Dog dog = new Dog();
Dog2 dog2 = new Dog2();
dog.name = "王二狗";
dog.height=114514;
dog2.name ="张三";
dog2.height=1919810;
System.out.println(dog.height);
System.out.println(dog.name);
dog.Bark();
System.out.println("_________________");
System.out.println(dog2.name);
System.out.println(dog2.height);
dog2.Bark();
}
}
this引用
public class L513 {
public static void main(String[] args) {
Date date = new Date();
Date date2 = new Date();
Date date3 = new Date();
// new三个Date的对象。
date.setDate(1991,2,3);
date2.setDate(1445,7,3);
date3.setDate(1,4,6);
}
}
public class Date{
public int date;
public int month;
public int year;
public void setDate(int x,int y, int z){
year = y;
month =x;
date = z;
}
public void printdate(){
System.out.println(year+" "+month+" "+date);
}
}
如果形参名字不小心和成员相同,
public void setDate(int year,int month, int date){
year = year;
month =month;
date = date;
}
但是上面输出的是0;因为setdate里的形参都是局部变量,不是成员变量。
解决方法为:
public void setDate(int year,int month, int date){
this.year = year;
this.month =month;
this.date = date;
}
需要引用this关键字。
this关键字
this引用是当前对象的引用,谁调用了方法,谁就是当前的this
this只能在成员方法和构造方法中引用
public void printdate(){
System.out.println(this.year+" "+this.month+" "+this.date);
}
//这里面也可以加this,最好用他防止报错。
第三种赋值方法
前两者已经提及前面内容,
通过成员方法赋值和直接赋值。
第三种就是构造方法(构造器)。
构造方法的方法名和类名保持一致,实例化时有编译器自动调用,且没有返回值。
public class L513 {
public static void main(String[] args) {
Dog dog = new Dog();
;
}
}
class Dog{
public Dog(){
System.out.println("构造方法");
//在这里就可以初始化成员变量了。
}
}
构造方法可以不带参数,编译器会自动提供一个不带参数的构造方法。但是如果写入了第二个构造方法,就不能屏蔽原来不带参数的构造方法。
public Date(int year,int month,int day){
this day =day;
this month = month;
this year = year;
}
构造方法可以满足方法的重载。每个构造方法只会调用一次
可以通过右键---gengrate---constructor然后选择参数来一键生成构造方法。
this:
this.属性 访问当前对象的属性
this() 调用当前对象的构造方法(必须放到构造方法里面,且是第一行,不能形成环的调用 )
this.func(方法)() 调用当前对象的成员方法
访问修饰限定符
public
在任何地方,都可以访问他修饰的成员或者类。
protected
在默认的基础上加上不同包的子类。
default
什么都不写时的默认权限,也就是同一个包中的不同类和同一类都可以使用。
private
只能在当前类中访问,在同一个包下的不同文件就不能访问了。
如果想要在同一个包的另一个类访问private,需要提供一个接口
class Date{
private int year;
public int month;
public int day;
public Date(){
System.out.println("没有函数的构造方法");
}
public Date(int year,int month,int day){
this.year=year;
this.month=month;
this.day=day;
System.out.println("三个函数的构造方法");
}
public void getyear(int year){
this.year = year;
}
public int setYear(){
return this.year;
}
//通过getyear和setyear两个接口来实现调用。
}
public class L514 {
public static void main(String[] args) {
}
}
//另一个类中
public class test {
public static void main(String[] args) {
Date date =new Date();
date.day=1;
date.month=2;
//date.year=3; 这一行就会报错了
date.getyear(1999);
System.out.println(date.setYear());
System.out.println(date.day);
}
}
接口也可以在idea里通过右键-- generate -- getters and setters来实现一键生成
public class test {
public static void main(String[] args) {
Date date =new Date();
date.day=1;
date.getyear(1999);
date.setDay(1888);
date.setMonth(1777);
//同理去进行赋值和打印。
System.out.println(date.setYear());
System.out.println(date.getDay());
System.out.println(date.getMonth());
System.out.println(date.day);
}
}
包
import java.util.*;
import java.sql.*;
//有时候一个包下会包含重复的类,这个时候需要指定是哪一个包下的类
public class L514 {
public static void main(String[] args) {
java.util.Date date = new java.util.Date();
java.sql.Date date1 = new java.sql.Date(12);
}
}
静态包
import java.util.*;
import java.sql.*;
//有时候一个包下会包含重复的类,这个时候需要指定是哪一个包下的类
import static java.lang.Math.*;
//导入一个math静态包
public class L514 {
public static void main(String[] args) {
java.util.Date date = new java.util.Date();
java.sql.Date date1 = new java.sql.Date(12);
int a = (int) Math.pow(2,2);
int b = (int) pow(2,2);
//导入静态包后,可以去掉Math.直接使用
}
}
一些常见的包
java.lang
系统常用基础类
java.lang.reflect:java
反射编程包
java.net
进行网络编程开发包
java.sql
进行数据库开发的支持包
java.utill
是java提供的工具程序包
java.io
I/O编程开发包
static修饰的成员变量(静态成员变量)和成员方法(类方法)
修饰后,该成员变量不会存在对象里面,而是存在了方法区,他不再属于对象。
因此不需要实例化就可以实现调用。需要通过类名去访问。
class Class{
public static int name = 1;
}
public class L514 {
public static void main(String[] args) {
System.out.println(Class.name);
}
}
方法同理,但是静态的方法中不能直接访问非静态的数据和方法
class Student {
public String name;
public double score;
public int age;
public static void staticFunc() {
Student student = new Student();
student.name = "fsa";
//需要通过在静态方法里面new对象后才能进行访问。
//和main函数需要new对象同理。
}
}
public class L514 {
public static void main(String[] args) {
}
}
或者
public static void staticFunc(Studen student) {
Student student = new Student();
student.name = "fsa";
//把类作为参数传进来也可以实现访问。
}
static成员变量初始化
一个是就地初始化,另外一个是静态代码块初始化
静态代码块初始化
代码块就是花括号括起来的内容{}
代码块可以分为四种,普通代码块(本地代码块),构造块(实例代码块),静态块,同步代码块。
普通代码块(本地代码块):
public void func(int a){
System.out.println(a);
{
System.out.println("本地代码块");
}
}
实例代码块 (类的内部,方法外部)
class Student {
public String name;
public double score;
public int age;
public void staticFunc() {
Student student = new Student();
student.name = "fsa";
}
{
System.out.println("实例代码块");
}
}
静态代码块
class Student {
public String name;
public double score;
public int age;
public void staticFunc() {
Student student = new Student();
student.name = "fsa";
}
static{
System.out.println("静态代码块");
}
}
一个类中,代码块执行顺序为 静态代码块 实例代码块 本地代码块,静态的最先被加载
如果有多个静态代码块,则要看执行顺序。
如果没有实例化对象,那么之后执行静态的。
静态的只会执行一次。
内部类
定义在一个类或者一个方法内部的类称做内部类
内部类有:
实例内部类
静态内部类
本地内部类
匿名内部类
实例内部类
public class L514 {
public static void main(String[] args) {
}
}
class dog{
public int length;
public void bark(){
}
class body{
public int heart;
}
}
//实例内部类中,不能定义静态的成员变量和成员方法
如果要定义static修饰的成员变量 需要在static后面加final修饰
class Dog{
public int length;
public void bark(){
}
public class Body{
public int heart;
public Body(){
System.out.println("实例内部类的构造方法");
}
public void func(){
System.out.println("实例内部类的方法");
//可以访问同一个类的成员变量,不论是否静态
}
}
}
public class L514 {
public static void main(String[] args) {
Dog.Body body = new Dog().new Body();
// 外部类类名.内部类 变量 = 外部类引用.new 内部类()
}
}
如果需要在内部类中访问外部类同名的成员变量,需要用
外部类.this.(成员变量)
的格式进行访问。
如果是静态的则是
外部类.(成员变量)
注意事项
外部类中的任何成员都可以被在实例内部类方法中直接访问。
实力内部类所处的位置和外部类成员位置相同,因此也会受到public等访问限定符的约束。
实例内部类对象必须先有外部类对象的前提下才可以创建。
外部类中,不能直接访问实力内部类的成员,要访问需要线创建外部类的对象。
静态内部类
class Dog{
public int length;
public void bark(){
}
static public class Body{
public int heart;
public Body(){
System.out.println("静态内部类的构造方法");
}
public void func(){
System.out.println("静态内部类的方法");
}
}
}
public class L515 {
public static void main(String[] args) {
Dog.Body body = new Dog.Body();
外部类类名.内部类 变量 = new 外部类.内部类()
body.func();
}
}
注意 在静态内部类中不能直接访问非静态的外部成员,body里就不能访问dog类的length成员变量
如果需要访问,需要实例化对象或者作为参数传入内部类。
局部内部类
定义在方法里面的类,不能被public等访问限定修饰符修饰。
编译器自动生成类的打印函数:
class Dog{
public int length;
public void bark(){
}
static public class Body{
public int heart;
public Body(){
System.out.println("静态内部类的构造方法");
}
public void func(){
System.out.println("静态内部类的方法");
}
@Override
public String toString() {
return "Body{" +
"heart=" + heart +
'}';
}
}
}
public class L515 {
public static void main(String[] args) {
Dog.Body body = new Dog.Body();
String ret = body.toString();
//去接收tostring的返回值
System.out.println(ret);
}
}
这里定义在了内部类中,外部类也可以定义
还可以通直接打印来输出
public class L515 {
public static void main(String[] args) {
Dog.Body body = new Dog.Body();
// body.func();
// String ret = body.toString();
System.out.println(body.toString());
}
}
此时打印的不再是地址,因为重写了tostring,重写后编译器不会调用原有的tostring