一、类和类的实例化
1.类就是一类对象的统称。对象就是这一类具体化的一个实例。一个类可以实例化无数个对象。
2.声明一个类就是创建一个新的数据类型,而类在java中属于引用类型,java使用关键字class来声明类。
3.基本语法
//创建类
class <class_name>{
field;//成员属性
method;//成员方法
}
//实例化对象
<class_name> <对象名> =new <class_name>();
代码示例:
class Person{
public int age;//成员属性 实例变量
public String name;
public static int a;//静态成员变量
public void eat(){//实例成员方法
System.out.println("吃饭!");
}
public void sleep(){
System.out.println("睡觉!");
}
public static void func(){
System.out.println("静态成员方法func()");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person=new Person();//通过new实例化对象,person是一个引用
System.out.println(person.name);
System.out.println(person.age);
//若访问静态的成员属性,对于静态的属性和方法是不依赖于对象的
System.out.println(Person.a);
person.eat();//成员方法调用需要通过对象的引用调用
person.sleep();
Person.func();//静态访问
//产生对象 实例化对象
Person person1=new Person();
Person person2=new Person();
}
}
结果:null 0 0 吃饭! 睡觉! 静态成员方法func()
如果成员变量没有初始化,那么值是默认的值。
如果是引用类型(String,Array,以及自定制类),那么值就是null,如果是简单类型,那么值就是这种类型所对应的默认值
简单类型有:byte—0 short—0 int—0 long—0L float —0.0f
double —0.0 char —’\u0000’ boolean—false
4.注意事项:(1)new关键字用于创建一个对象的实例。
(2)使用 . 来访问对象中的属性和方法。
5.字段就地初始化
(1)就地初始化
class Person1{
public String name="张三";
public int age=10;
}
public class TestDemo2 {
public static void main(String[] args) {
Person1 person1=new Person1();
System.out.println(person1.name);//张三
System.out.println(person1.age);//10
}
}
(2)默认初始化
(3)类外初始化
class Person1{
public String name;
public int age;
}
public class TestDemo2 {
public static void main(String[] args) {
Person1 person1=new Person1();
person1.name="张三";
System.out.println(person1.name);//张三
person1.age=10;
System.out.println(person1.age);//10
}
}
二、static关键字
1.修饰属性:java静态属性和类相关,和具体的实例无关。
class testDemo{
public int a;
public static int count;
}
public class TestDemo3 {
public static void main(String[] args) {
testDemo t1=new testDemo();
t1.a++;
testDemo.count++;
System.out.println(t1.a); //输出结果:1
System.out.println(testDemo.count); //1
System.out.println("=============");
testDemo t2=new testDemo();
t2.a++;
testDemo.count++;
System.out.println(t2.a); //1
System.out.println(testDemo.count); //2
}
}
2.修饰方法:如果在任何方法上应用static关键字,此方法称为静态方法。
(1)静态方法属于类,而不属于类的对象。(2)可以直接调用静态方法,而无需创建类的实例。(3)静态方法可以访问静态数据成员,并可以更改静态数据成员的值。
class testDemo{
public int a;
public static int count;
public static void change(){
count=10;
//a=10; error 不可以访问非静态数据成员
}
}
public class TestDemo3 {
public static void main(String[] args) {
testDemo.change();//静态方法无需创建实例对象就可以调用
System.out.println(testDemo.count); //10
}
}
注意事项1:静态方法和实例无关,而是和类相关。因此导致这两种情况:(1)静态方法不能直接使用非静态数据成员或调用非静态方法(非静态数据成员和方法都是和实例相关的)(2)this和super两个关键字不能在静态上下文中使用(this是当前实例的引用,super是当前实例父类实例的引用,也是和当前实例相关)
注意事项2:(1)我们曾经写的方法为了简单,都统一加上了static。但实际上一个方法具体要不要带static,都需要是情形而定。(2)main方法为static方法。
三、内存布局
1.代码示例:
class Person4{
public int age;//实例变量 存放在对象内
public String name;//实例对象
public String sex;//实例变量
public static int count;//类变量也叫静态变量,编译时已经产生,属于类本身,且只有一份。存放在方法区
public final int size=10;//被final修饰的叫常量,也属于对象。被final修饰,后续不可更改
public static final int COUNT=99;//静态的常量,属于类本身,只有一份,被final修饰,后续不可更改
//实例成员函数
public void eat(){
int a=10;//局部变量
System.out.println("eat()!");
}
//实例成员函数
public void sleep(){
System.out.println("sleep()!");
}
//静态成员函数
public static void staticTest(){
//不能访问非静态成员
//sex="man";error
System.out.println("staticTest()!");
}
}
public class TestDemo4 {
public static void main(String[] args) {
//产生对象 实例化对象
Person4 person4=new Person4();
System.out.println(person4.age);
System.out.println(person4.name);
System.out.println(Person4.count);
System.out.println(Person4.COUNT);
Person4.staticTest();
person4.eat();
person4.sleep();
}
}
2.输出结果:
3.数据属性的内存布局
四、封装
1.软件开发的本质就是对程序复杂程度的管理。如果一个软件代码复杂程度太高,那么就无法继续维护。如何管理复杂程度?封装就是最基本的方法。
在我们写代码时经常会涉及两种角色:类的实现者和类的调用者。
封装的本质就是让类的调用者不必太多的了解类的实现者是如何实现类的。
这样就降低了类使用者的学习和使用成本,从而降低了复杂程度。
2.private实现封装
private/public这两个关键字表示“访问权限控制”。
(1)被public修饰的成员变量或者成员方法,可以直接被类的调用者使用
(2)被private修饰的成员变量或者成员方法,不能被类的调用者使用。
3.代码示例:
(1)直接使用public
class Person2{
public String name="张三";
public int age=18;
}
public class TestDemo4 {
public static void main(String[] args) {
Person2 person2=new Person2();
System.out.println("我叫"+person2.name+",今年"+person2.age);
}
}
执行结果:我叫张三,今年18
(a)这样的代码导致类的使用者(main方法的代码)必须要了解Person2类内部的实现,才能使用这个类。
(b)一旦类的实现者修改了代码,那么类的使用者就需要大规模的修改自己的代码,维护成本较高。
(2)使用private封装属性,并提供public方法供类的调用者使用
class Person3{
private String name="张三";
private int age=18;
public void show(){
System.out.println("我叫"+name+",今年"+age);
}
}
public class TestDemo4 {
public static void main(String[] args) {
Person3 person3=new Person3();
person3.show();
}
}
执行结果:我叫张三,今年18
(a)此时字段已经使用了private来修饰,类的调用者(main方法中)不能直接使用,而需要借助show方法。此时类的使用者就不必了解Person3类的实现细节。
(b)同时类的实现者修改了字段的名字,类的调用者不需要做出任何的修改(类的调用者根本访问不到name,age这样的字段)。
(c)private不光能修饰字段,也能修饰方法。
(3)getter和setter方法
class Person3{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;//this引用,表示调用该方法的对象
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void show(){
System.out.println("name:"+name+" age:"+age);
}
}
public class TestDemo4 {
public static void main(String[] args) {
Person3 person3=new Person3();
person3.setName("bit");
String name=person3.getName();
person3.setAge(18);
int age=person3.getAge();
person3.show();
}
}
运行结果:name:bit age:18
注意事项:(a)getName,getAge即为getter方法,表示获取这个成员的值。
(b)setName,setAge即为setter方法,表示设置这个成员的值。
(c)当set方法的形参名字和类中的成员属性的名字一样时,如果不使用this,相当于自赋值,this表示当前实例的引用。若是静态方法,则不能用this。
五、构造方法
1.构造方法是一种特殊的方法,使用关键字new实例化新对象时会被自动调用,用于完成初始化操作。
2.面试问题:实例化一个对象/创建一个对象分为几步?
new执行过程:(1)为对象分配内存空间(2)调用对象的构造方法
3.语法规则:(1)方法名称必须与类名称相同
(2)构造方法没有返回值类型说明
(3)每一个类中至少存在一个构造方法
4.代码示例:
class Person5{
private String name;//实例成员变量
private int age;
private String sex;
//默认构造函数 构造对象
public Person5(){
this.name="bit";
this.age=18;
this.sex="女";
}
//带有三个参数的构造函数,通过Shift+箭头选中多个参数
public Person5(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public void show(){
System.out.println("name:"+name+" age:"+age+" sex:"+sex);
}
}
public class TestDemo4 {
public static void main(String[] args) {
Person5 p1=new Person5();
p1.show();
Person5 p2=new Person5("bitttt",18,"女");
p2.show();
}
}
执行结果:name:bit age:18 sex:女
name:bitttt age:18 sex:女
六、this关键字
1.this表示当前对象引用
2.代码示例:
//默认构造函数 构造对象
public Person5(){
//this调用构造函数
this("bit",18,"女");//必须放在第一行进行显示
}
//这两个构造函数之间的关系为重载
public Person5(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
七、认识代码块
1.使用{ }定义的一段代码,可分为:普通代码块,构造块,静态块,同步代码块
2.代码示例:
class Person6{
private String name;//实例成员变量
private int age;
private String sex;
private static int count=0;
public Person6() {
System.out.println("I am Person init()!");
}
//实例代码块
{
this.name="bit";
this.age=18;
this.sex="女";
System.out.println("I am instance init()!");
}
//静态代码块
static {
count=10;//只能访问静态数据成员
System.out.println("I am static init()!");
}
public void show(){
System.out.println("name:"+name+" age:"+age+" sex:"+sex);
}
}
public class TestDemo4 {
public static void main(String[] args) {
//直接使用{}定义,普通代码块
Person6 person6=new Person6();
}
}
执行结果:I am static init()!
I am instance init()!
I am Person init()!
3.注意事项:(1)静态代码块不管生成多少个对象,其只会执行一次
(2)先执行静态代码块,然后执行实例代码块(构造块),再然后是构造函数执行。
4.匿名对象:(1)没有引用的对象(2)只能在创建对象时使用
public static void main(String[] args){
new Person("bit",18,"女").show();//通过匿名对象调用方法
}