1.封装
1.1 private 实现封装
代码示例:主方法存在于Person类的外部,Person类的私有属性对其他类不可见,访问时会报错
public static void main(String[] args) {
Person per = new Person();
per.name = "张三"; //会报错
System.out.println(per.name);
}
}
class Person {
private String name;
private int age;
private String sex;
}
但是当主方法存在于当前类Person的内部,私有属性就是可见的,访问时不会报错。
class Person {
private String name;
private int age;
private String sex;
public static void main(String[] args) {
Person per = new Person();
per.name = "张三";
System.out.println(per.name);
}
}
//执行结果为
张三
那么问题来了,如果我们想要在类的外部去使用私有属性该怎么办呢?
这时就需要使用类提供的getter(取值)和setter(修改值)方法了~
1.2 getter 和 setter 方法
public class Practice {
public static void main(String[] args) {
Person per = new Person();
per.getName();
System.out.println(per.getName());
per.setName("小明");
System.out.println(per.getName());
}
}
class Person {
private String name = "张三";
private int age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//执行结果为
张三
小明
2.构造方法
使用关键字new产生一个对象时,大致分为以下两步:
1.为对象在堆中分配空间
2.调用对象的构造方法为对象成员变量赋值
语法规则:
1.方法名称必须与类名称相同
2.构造方法没有返回值类型声明(不是void)
3.每一个类中一定至少存在一个构造方法(若没有明确定义,则系统会自动生成一个默认的无参构造)
代码示例:使用new实例化对象时会自动调用该类的构造方法
public class Practice {
public static void main(String[] args) {
Person per = new Person();
}
}
class Person {
private String name = "张三";
private int age;
private String sex;
public Person() {
System.out.println("Person的构造方法");
}
}
//执行结果为
Person的构造方法
如果没有明确定义构造方法,系统会自动生成一个默认的无参构造,不会报错。
public class Practice {
public static void main(String[] args) {
Person per = new Person(); //调用了无参构造
}
}
class Person {
private String name = "张三";
private int age;
private String sex;
}
执行结果如图:
注意:当类中自定义了构造方法时,默认的无参构造就不再生成!
public class Practice {
public static void main(String[] args) {
Person per = new Person();
}
}
class Person {
private String name = "张三";
private int age;
private String sex;
public Person(String a) {
name = a ;
System.out.println("Person的有参构造");
}
}
执行结果为:(因为new对象时调用的是无参构造,而此时并没有无参构造,所以会报错)
public class Practice {
public static void main(String[] args) {
Person per = new Person();
Person per1 = new Person("张三" );
Person per2 = new Person("小明",18);
}
}
class Person {
private String name = "张三";
private int age;
private String sex;
public Person() {
System.out.println("Person的无参构造");
}
public Person(String a) {
name = a ;
System.out.println("姓名为:" + name);
System.out.println("Person的一个参数的有参构造");
}
public Person(String a,int b) {
name = a ;
age = b;
System.out.println("姓名为:" + name + ",年龄为:" + age);
System.out.println("Person的两个参数的有参构造");
}
}
//执行结果为
Person的无参构造
姓名为:张三
Person的一个参数的有参构造
姓名为:小明,年龄为:18
Person的两个参数的有参构造
注意:JVM产生对象时调用构造方法,对象实例化结束后是无法在程序中手动调用构造方法再次实例化对象的。
3. this 关键字
3.1调用当前对象的成员变量
代码示例:使用 this.属性名称 打破类的就近匹配原则
public class Practice {
public static void main(String[] args) {
Person per = new Person("小明",18,"男");
per.show();
}
}
class Person {
private String name;
private int age;
private String sex;
public Person(String name,int age,String sex) {
name = name;
age = age;
sex = sex;
System.out.println("Person有参构造");
}
public void show() {
System.out.println("姓名为:" + name + ",年龄为:" + age + ",性别为:" + sex);
}
}
//执行结果为
Person有参构造
姓名为:null,年龄为:0,性别为:null
图片解释:就近匹配,相当于形参自己等于自己
使用this关键字后:打破就近匹配,执行结果为:姓名为:小明,年龄为:18,性别为:男
3.2调用类中的方法
3.2.1调用类中的成员方法
public class Practice {
public static void main(String[] args) {
Person per = new Person();
per.show();
per.fun();
}
}
class Person {
private String name;
private int age;
private String sex;
public void show() {
System.out.println("Person类的show成员方法");
}
public void fun() {
show(); //相当于this.show(),所以不会报错
System.out.println("Person类的fun成员方法");
}
}
//执行结果为
Person类的show成员方法
Person类的show成员方法
Person类的fun成员方法
可以看出show方法是成员方法,按理应该通过对象来调用,但此时并没有通过对象调用,而且也没有报错,这是因为在编译器编译之后默认会加上this。
3.2.2构造方法间的相互调用
代码示例:可以看出不同参数的构造方法之间出现了重复的调用
public class Practice {
public static void main(String[] args) {
Person per1 = new Person();
Person per2 = new Person("小明");
Person per3 = new Person("小明",18);
}
}
class Person {
private String name;
private int age;
private String sex;
public Person () {
System.out.println("***************");
}
public Person (String name) {
System.out.println("***************");
this.name = name;
}
public Person (String name,int age) {
System.out.println("***************");
this.name = name;
this.age = age;
}
}
//执行结果为
***************
***************
***************
如果不同参数的构造方法之间出现了重复的调用,可以使用this(参数)调用其他的构造方法。
3.2.3表示当前对象的引用(了解即可)
this表示当前对象的引用,即当前是通过哪个对象调用的属性或方法,this就指代谁。(像一面镜子一样)
public class Practice {
public static void main(String[] args) {
Person per1 = new Person();
System.out.println(per1);//直接打印一个引用数据类型会输出对象的地址
per1.show();
}
}
class Person {
private String name;
private int age;
private String sex;
public void show () {
System.out.println(this);
}
}
//执行结果为
Person@4eec7777
Person@4eec7777
4.代码块
4.1普通代码块
定义在方法中的代码块。
public static void main(String[] args) {
{
//普通代码块
int a = 10;//作用域只在该代码块中
}
int a = 20;
System.out.println(a);
}
//执行结果为
20
4.2成员代码块
定义在类中的不加任何修饰符的代码块。
public class Practice {
public static void main(String[] args) {
Person per1 = new Person();
Person per2 = new Person();
}
}
class Person {
String name;
{
//构造块
System.out.println("Person的构造块");
}
public Person () {
System.out.println("Person的无参构造");
}
}
//执行结果为
Person的构造块
Person的无参构造
Person的构造块
Person的无参构造
4.3静态代码块
定义在类中使用static修饰的代码块,在类加载时执行一次,只执行一次。
public class Practice {
public static void main(String[] args) {
Person per1 = new Person();
Person per2 = new Person();
}
}
class Person {
String name;
{
//构造块
System.out.println("Person的构造块");
}
public Person () {
System.out.println("Person的无参构造");
}
static {
//静态块
System.out.println("Person的静态代码块");
}
}
//执行结果为
Person的静态代码块
Person的构造块
Person的无参构造
Person的构造块
Person的无参构造
代码解析:static int age = 18; 存在于方法区,初始值为18,此时Person类只是定义而没有加载;当主方法中使用了Person类,就需要把Person加载到内存中,类一加载静态代码块就执行了,所以最后的值就为20。
public static void main(String[] args) {
System.out.println(Person.age);
}
}
class Person {
static int age = 18;
static {
age = 20;
System.out.println("Person的静态代码块");
}
}
//执行结果为
Person的静态代码块
20
5.补充
5.1匿名对象
匿名对象就是new出来的对象,没有引用指向(没有名字),使用一次后就销毁了。匿名对象常用于测试类中的某些功能。
5.2 toString 方法
当一个引用类型的变量调用printIn函数打印时,默认输出的都是引用类型的地址(不是真正的内存地址)。
敲重点啦~~