类的定义:类就是对现实生活中的事物的抽象,将其变为一个大的集合,这个事物基本都可以用这个类来进行创建。创建出来的就叫做这个类的对象。
类的定义格式
class ClassName{
field;//(类的属性就是这个物有啥类似于手机有屏幕也有电池cpu等)成员变量
method;//(行为就是这个物咋样的各个运行部分比如手机运行时手机屏幕亮电池还要cpu和其他功能展示)成员方法
}
eg
class WashMachine{
public String brand;//品牌
public String type;//型号
public double weight; //重量
public double length; //长
public double width; //宽
public double height; //高
public String color;//颜色
public void washClothes(){//洗衣服
System.out.println("洗衣功能");
}
public void dryClothes(){//脱水
System.out.println("脱水功能");
}
public void setTime(){//定时
System.out.println("定时功能");
}
}
注
类名建议使用大驼峰。
成员方法写为public为了在类的外面还能使用这个方法
此次这个方法不带sataic是因为加了之后就变成可以直接通过类来直接使用这个也就是这个类创建的所有对象只能使用这一个,导致可能出现不同对象的访问(???)
类的实例化
类的实例化就是用这个类创建了一个对象,类似于现实生活中用相同功能的手机组件可以创建不同手机品牌的手机。
class PetDog {//狗的属性
public string name;//名字
public string color;//颜色
//狗的行为
public void barks() {
system.out.println(""旺旺旺~~~");
}
public void wag(){
system.out.println("摇尾巴~~~" );
}
}
public class Main{
public static void main(String]args){
PetDog dogh = new PetDog();//通过new实例化对象
dogh.name ="阿黄";
dogh.color = "黄";
dogh.barks();
dogh.wag();
}
最后就会输出旺旺旺,摇尾巴~~~这两个动作,然后你也可以发现他将这只狗的名字设置为阿黄,颜色为黄色。
注
使用new关键字来创建一个对象
使用.可以访问对象中的方法和属性
同一个类可以创建多个对象
类和对象的关系
类就像是一个模型,可以使创建出来的对象约束在这个模型里,但其具体细节部分可以自己进行修改(类有点类似设计图,通过这个设计图可以建造出不同的房子但最后创建的房子的外部风格差不多一样最多只有里面的房间有些差别)。
类的this引用
public class Date {
public int year;
public int month;
public int day;
public void setDay(int y, int m, int d){
year = y;
month = m;
day = d;
}
public void printDate(){
System.out.printIn(year + "/" + month + "/" + day);
}
public static void main(String[] args){构造三个日期类型的对象d1 d2 d3
Date d1 = new Date();
Date d2 = new Date();
Date d3 = new Date();
//对d1,d2,d3的日期设置
d1.setDay(2020,9,15);
d2.setDay(2020,9,16);
d3.setDay(2020,9,17);
//打印日期中的内容
d1.printDate();
d2.printDate();
d3.printDate();
}
}
上述代码中的形参代码与成员变量名相同不会影响赋值吗?还有三个对象都在使用打印日期,设置日期的成员方法他们会不会因为方法名相同导致对象的变量传递错了一个对象设置的日期和他打印的日期不同。这些问题的解决就是依靠this引用,this引用会调用当前对象的成员方法和变量,类似于上面的操作时都是于this引用实现的,只不过他一般是隐式调用,但是我们在以后的使用中必须加上this.引用以便代码可读性性更强。
注
this引用只能在成员方法中使用
在成员方法中this引用只能引用当前,不能引用其他对象
对象的构造和初始化
public class Date {
public int year;
public int month;
public int day;
public void setDay(int y, int m, int d){
year = y;
month = m;
day = d;
}
public void printDate(){
System.out.printIn(year + "/" + month + "/" + day);
}
public static void main(Stringl]args){
Date d = new Date();
d.printDate();
d.setDate(2021,6,9);
d.printDate();
}
上述代码中我们都是先建立一个类的对象然后在给这个对象赋值,这样比较麻烦。以及那个打印日期没有给他赋初值他还可以正常使用(因为在类里面的成员变量如果没有赋初值时,系统会自动赋给值一般为0).
上面要解决的先建立对象在给对象赋值这个可以通过调用构造方法来实现
public class Date {
public int year;
public int month;
public int day;
//构造方法:
//名字与类名相同,没有返回值类型,设置为void也不行一般情况下使用public修饰
//在创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
public Date(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
System.out.println("Date(int,int,int)方法被调用了");}
public void printDate(){
System.out.println(year + "." + month + "-" + day);
}
public static void main(String[]args){
//创建了一个Date类型的对象,并没有显式调用构造方法
Date d = new Date(2021,6,9);//输出Date(int,int,int)方法被调用了
d.printDate(); // 2021-6-9
此代码就使用了构造方法的调用在直接创建对象并且赋初值
注
构造方法的名字必须和类名一样
没有返回值类型void也不行
创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
构造方法可以进行重载
eg//构造方法的重载
public Date(){
this.year = 1900;
this.month = 1;
this.day = 1;
}
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
一个是无参时,一个是有参数时。
构造参数系统一般会默认分配一个不带任何参数也不给系统的成员变量赋初值,并且一旦定义一个构造参数,那么系统不会分配默认的构造方法。
eg:
public Date(){
}
封装:java是一个面向对象的语言面向对象的语言的三大特性之一就是封装封装正好又是类的关键作用。封装的具体作用就是将数据和数据操作的方法结合起来放在一起,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互操作。
访问权限:java中主要通过类和访问权限的设置来实现封装。类的作用就是封装的作用。访问权限就是控制对外接口也就是方法或者属性直接在类外使用。访问权限不仅可以控制成员属性和方法也可呀控制类。
public:就是谁都可以看到里面的具体属性(如看见小狗的颜色大小种族体型)
default:是只有关系比较亲近的人才能知道(如自己的小名一般只有同一家族的人并且这是默认时的权限)
private:是只有自己知道的并且不会告诉别人的(如银行卡密码以及其他等关键信息)
protected:被其修饰的成员对于本包和其子类可见(其实意思就是如果在一个包内的话这个包内的所有成员都可以访问这个权限修饰的,不在一个包内的子类对象只能访问从父类中继承的方法并且还不能访问父类对象的protected方法,并且还不能访问其他子类对象的protected方法,还有父类不能访问子类对象中没有继承protected的方法,但可以访问子类继承protected方法)。
包:java中的包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式。比如一个包中的类一般不允许其他包来使用。还有就是可以建立相同的类名在同一个工程项目下面,只要不在同一个包即可。
导入包中的类:java中有很多现成的类可以来使用,只不过是我们必须导入他所在的那个包如同C语言的头文件一样。
import java.util.Date;
public class Test {
public static void main(String[]args){
Date date = new Date();
//得到一个毫秒级别的时间戳
System.out.printIn(date.getTime());}
}
类似这样improt导入一个包就可以使用data这个类来得到时间戳(一般就是本机电脑的时间)如果想一次导入一个包一个包里含有多个类可以导入import java.util.*;这个*号的意思就是通配符它可以和util.里面的所有包只要前缀是util.进行匹配搜索只要你使用的类在这个里面就可以使用。一般建议不使用这因为有包与包之间的类名称一样但功能不一样。
静态成员变量:被stacic修饰的类的属性,不属于某个具体的对象,是所有对象共享的,不存储在某个对象的空间中。
既可以通过类名来访问,也可以通过对象名来访问,但一般推荐类名来访问
存储于方法区中。
生命周期随类的生命周期
public class Student{
public String name;
public String gender;
public int age;
public double score;
public static String classRoom = "Bit306";
public static void main(String[] args){
//静态成员变量可以直接通过类名访问
System.out.println(Student.classRoom);
Student s1 = new Student("Li leilei", "男",18,3.8);
Student s2 = new Student("Han MeiMei", "女",19,4.O);
Student s3 = new Student("Jim","男",18,2.6);
//也可以通过对象访问:但是classRoom是三个对象共享的
System.out.println(s1.classRoom);
System.out.println(s2.classRoom);
System.out.printIn(s3.classRoom);
静态成员方法:被static修饰的类的成员方法,不是某个对象持有的。所有共用一个是类方法。
可以通过对象调用也可呀通过类名.静态方法名()来调用一般使用后者。
不能在静态方法中访问任何非静态成员变量。
静态方法不能调用任何非静态方法,因为非静态方法有this参数,静态方法没有。
静态成员变量一般通过静态成员方法访问。
public class Student{
private static String classRoom= "Bit306";
public static String getClassRoom(){
return classRoom;
}
}
public class TestStudent {
public static void main(String[ args) {
System.out.printIn(Student.getClassRoom());
}
}
静态成员变量初始化:就地初始化
public class Student{
private String name;
private String gender;
private int age;
private double score;
private static String classRoom = "Bit306";
}
代码块
使用{ } 定义的一段代码称为代码块而根据代码块的位置以及关键词又分为普通代码块,构造代码块,静态代码块
普通代码块
定义在方法中的代码块
public class Test {
{
System.out.println("这是第一个普通代码块");
}
public Test() {
System.out.println("这是构造函数");
}
{
System.out.println("这是第二个普通代码块");
}
public static void main(String[] args) {
Test test1 = new Test();
}
}
输出结果
这是第一个普通代码块
这是第二个普通代码块
这是构造函数
从输出结果中我们可以看出普通代码块的执行顺序是先于构造函数,但其本身的普通代码块中的执行顺序是按照在代码中的上下顺序
构造代码块
一般也叫实例化代码块用来初始化成员变量
public class Student{
//实例成员变量
private String name;
private String gender;
private int age;
private double score;
public Student() {
System.out.println("I am Student init()!");
}
//实例代码块
{
this.name = "bit";
this.age = 12;
this.sex = "man";
System.out.println("l am instance init()!");
}
public void show(){
System.out.printIn("name: "+name+" age: "+age+" sex: "+se);
}
public class Main {
public static void main(String]args){
student stu = new Student();
stu.show();
}
输出结果
l am instance init()!
l am Student init()!
name: bit age: 12 sex: man
从结果中也可以看出构造代码块和普通代码的区别只是在有没有对成员变量进行初始化其执行顺序依旧在构造函数之前。
静态代码块
一般用于初始化静态成员变量。
public class Student{
private String name;
private String gender;
private int age;
private double score;
private static String classRoom;
{
//实例代码块
this.name = "bit";
this.age = 12;
this.gender = "man";
System.out.printIn("I am instance init()!");
}
{
//静态代码块static
classRoom = "bit306";
System.out.println("I am static init()!");
}
public Student(){
System.out.println("I am Student init()!");
}
public static void main(String[] args){
student s1 = new Student();
Student s2 = new Student();}
}
输出
I am static init()!
I am instance init()!
I am Student init()!
I am instance init()!
I am Student init()!
从输出结果可以看到静态代码块最先被执行任何在执行构造代码块然后是构造函数,只不过静态代码块只会执行一遍。
注
如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行
实例代码块只有在创建对象时才会执行
内部类
就是将一个物体封装之后,又发现最好将这个物体的里面的一部分进行再次封装,并且这个被封转的内部还是为这个外部服务的。java中就将这个前者成为成为内部类,后者是外部类。
public class OutClass {
class InnerClass{
}
}
outClass是外部类
lnnerClass是内部类
注
定义在class类名书花括号外部的,即使是在一个文件里,都不能称为内部类
如下
public class A{
}
class B{
}
这是两个独立的类无关。
内部类被分为成员内部类和静态内部类以及匿名内部类
public class OutClass {
private int a;
static int b;
int c;
public void methodA(){
a= 10;
System.out.println(a);
}
public static void methodB(){
System.out.println(b);
}
//实例内部类:未被static修饰
class InnerClass{
int c;
public void methodInner()(
/在实例内部类中可以直接访问外部类中:任意访问限定符修饰的成员
a = 100;
b =200;
methodA();
methodB();
//如果外部类和实例内部类中具有相同名称成员时,优先访问的是内部类自己的
c = 300;
System.out.println(c);
//如果要访问外部类同名成员时候,必须:外部类名积.this.同名成员名字
OutClass.this.c = 400;
System.out.printIn(OutClass.this.cx)
}
}
public static void main(String[ args){
//外部类:对象创建以及成员访问
OutClass outClass=newOutClass() ;
System.out.println(outClass.a);
System.out.println(OutClass.b);
System.out.println(outClass.c);
outClass.methodA();
outClass.methodB0;
//创建实例内部类对象
OutClass.InnerClass innerClass1 = new OutClass().new lnnerClass();
//上述语法比较怪异,也可以先将外部类对象先创建出来,然后再创建实例内部类对象OutClass.InnerClass innerClass2 = outClass.new InnerClass();
innerClass2.methodInner();
}
}
注
外部类中的任何成员都可以在实例内部类方法中直接访问
实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束
在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须:外部类名称.this.同名成员来访问
实例内部类对象必须在先有外部类对象前提下才能创建
实例内部类的非静态方法中包含了一个指向外部类对象的引用
外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象。
静态内部类
被static修饰的内部类
public class OutClass {
private int a;
static int b;
public void methodA(){
a = 10;
System.out.println(a);
}
public static void methodB(){
System.out.println(b);
}
//静态内部类:被static修饰的成员内部类
static class InnerClass{
public void methodInner(){
//在内部类中只能访问外部类的静态成员
// a = 100;编译失败,因为a不是静态成员变量
b =200;
//methodA();编译失败,因为methodB()不是类静态成员方法
methodB();
}
public static void main(Stringargs){
//静态内部类对象创建&成员访问
outClass.InnerClass innerClass = new OutClass.InnerClass();
innerClass.methodInner();
}
注
在静态内部类中只能访问外部类中的静态成员如果
创建静态内部类对象时,不需要先创建外部类对象
如果想访问非静态成员变量或者非静态成员方法,我们该如何做?
通过外部类的对象访问:在静态内部类中创建外部类的对象,然后通过该对象访问非静态成员变量或方法。
public class Outer {
private int nonStaticVar = 10;
public void nonStaticMethod() {
System.out.println("Non-static method");
}
static class Inner {
public void accessOuter() {
Outer outer = new Outer();
System.out.println(outer.nonStaticVar);
outer.nonStaticMethod();
}
}
public static void main(String[] args) {
Inner inner = new Inner();
inner.accessOuter();
}
}
通过构造方法传递外部类对象:在静态内部类中定义一个构造方法,接受外部类对象作为参数,并在内部使用该对象访问非静态成员变量或方法。
public class Outer {
private int nonStaticVar = 10;
public void nonStaticMethod() {
System.out.println("Non-static method");
}
static class Inner {
private Outer outer;
public Inner(Outer outer) {
this.outer = outer;
}
public void accessOuter() {
System.out.println(outer.nonStaticVar);
outer.nonStaticMethod();
}
}
public static void main(String[] args) {
Outer outer = new Outer();
Inner inner = new Inner(outer);
inner.accessOuter();
}
}