目录
了解面向对象和面向过程
面向过程
面向对象
类和类的实例化
类的组成
实例化一个的对象
类的成员
普通成员
静态成员变量
注意事项
(面试)main函数为什么是static的?
引用一定存储在栈上吗?
封装
toString的重写
private实现封装,get和set
构造方法
this和super有什么区别
代码块
认识代码块
代码块如何被调用?
了解面向对象和面向过程
面向过程
面向对象
类和类的实例化
类的组成
class {
//成员属性
//成员方法
}
实例化一个的对象
class{ //成员属性 //成员方法 }
实例化一个的对象
class Person{
//字段 属性 成员变量(普通成员变量,静态成员变量)
public String name;
public int age;
//方法->行为 (普通成员方法,静态成员方法)
public void eat(){
System.out.println(name + "在吃饭");
}
public void Do(){
System.out.println(name + "在做作业");
}
}
类的成员
普通成员
1.普通成员变量的访问需要通过对象的引用来访问(普通的成员变量都是属于对象的)
class Person{
//字段 属性 成员变量(普通成员变量,静态成员变量)
public String name;
public int age;
//方法->行为 (普通成员方法,静态成员方法)
public void eat(){
System.out.println(name + "在吃饭");
}
public void Do(){
System.out.println(name + "在做作业");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person1 = new Person();
person1.name = "phf";
person1.age = 19;
//普通成员变量的访问需要通过对象的引用来实现
System.out.println(person1.name);
System.out.println(person1.age);
}
}
2.person定义在main中为局部变量,其引用存储在内存的栈上,内容存储在堆上。每个变量person都有各自的name,person,以及方法,修改一个person的成员变量,另一个不变。
3.调用对象上的普通成员方法,对象中的方法存储在内存的方法区,对象引用方法才会在栈上开辟空间。
class Person{
//字段 属性 成员变量(普通成员变量,静态成员变量)
public String name;
public int age;
//方法->行为 (普通成员方法,静态成员方法)
public void eat(){
System.out.println(name + "在吃饭");
}
public void Do(){
System.out.println(name + "在做作业");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person1 = new Person();
person1.name = "phf";
person1.age = 19;
//普通的成员方法需要用引用来调用
person1.Do();
person1.eat();
}
}
静态成员变量
静态成员变量被stastic修饰,通常保存在方法区(存储代码片段)。静态成员变量不属于对象,只属于类,也称为类变量。
静态成员变量放在内存什么地方?
1.首先了解编译过程
2. 静态成员变量存储在方法区
字节码文件当中包含了当前类的一些信息、代码片段和静态成员变量也都会存储在方法区。静态成员变量的调用方法为<类名>.<静态成员方法名>。
class Person{
//静态成员变量(类变量)
public static int count;
}
public class TestDemo {
public static void main(String[] args) {
//实例化一个person1对象
Person person1 = new Person();
//类调用静态成员变量
Person.count++;
System.out.println(Person.count);
}
}
注意事项
1.普通方法里面不能定义静态变量。
//普通方法
public void func(){
int a = 0;
static int b = 1;
}
以上定义方法是错误的,
①静态变量本身属于类,但定义在方法中,属于方法;不合适。
②调用普通方法需要引用来调用,但静态成员方法又不用引用,二者相矛盾。
2.静态方法(类方法)中不能定义静态成员变量。
//静态方法内不能定义静态成员变量
public static void func(){
int a = 0;
static int b = 1;
}
以上定义方法是错误的,
①静态变量本身也属于类,但定义在方法中,属于方法;不合适。
1,2可总结出,静态的变量是不能定义在方法中的。
3.普通方法中可以调用静态方法(类方法)。
//普通方法中可以调用静态方法
public void func(){
int a = 0;
staticFunc();
}
以上的调用方法是正确的,
①普通方法依赖对象而静态方法不依赖对象,调用了普通方法也有了调用静态方法的条件。
4.静态方法(类方法)中不可以调用普通方法
//静态方法(类方法)中不可以调用普通方法
public static void staticFunc(){
System.out.println("5555");
func();
}
以上调用方法是错误的,
①静态方法不依赖对象而普通方法以来对象,调用静态方法不具备调用普通方法的条件。
3,4可以总结出,静态方法中只能调用静态方法。
(面试)main函数为什么是static的?
main函数是否为static都是可以的的,取决与JVM在处理main函数时的处理逻辑。
引用一定存储在栈上吗?
class Person{
//普通成员变量
public String name;
public int age;
}
public class TestDemo {
Person person1 = new Person();
public static void main(String[] args) {
TestDemo testDemo = new TestDemo();
}
}
例如以上代码,在内存中的存储情况为:
new了一个testdemo对象为局部变量储在栈上,其内容存储在堆上;而一个对象testdemo其内容中有new了一个person1对象,会占用其一块内容,person1内容同样存储在堆上。
封装
1.在我们写代码的时候经常会涉及两种角色: 类的实现者和类的调用者.
2.封装的本质就是让类的调用者不必太多的了解类的实现者是如何实现类的, 只要知道如何使用类就行了.
3.这样就降低了类使用者的学习和使用成本, 从而降低了复杂程度.
toString的重写
public static void main(String[] args) {
Person person = new Person();
System.out.println(person);
}
此时打印输出结果为:Person@1b6d3586
1.当我们用println打印一个对象是输出的是一个地址,调了多个方法及toString()最终实现:
2.当我们自己在类中重写toString方法,编译时会优先调用自己定义的toString方法:
class Person{
//字段 属性 成员变量(普通成员变量,静态成员变量)
public String name;
public int age;
public String toString(){
return "phf";
}
}
public class TestDemo {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person);
}
}
此时输出结果为:phf
3.编译器可自行生成toString函数:
最终可以通过重写生成的toString方法直接修改输出值。
private实现封装,get和set
private和public这两个关键字表示“访问权限控制”
被 public 修饰的成员变量或者成员方法, 可以直接被类的调用者使用. 被 private 修饰的成员变量或者成员方法, 不能被类的调用者使用.
1.当定义的一个类的成员变量名被修改时,后续使用该类的代码的都会受到影响,所以应该将当前变量用private属性定义,起到封装作用。只能在类中使用它。这样所定义的变量会更加安全。
class Person{
//普通成员变量
private String name;
public int age;
}
2.这时,想要修改name的值只能在类中定义方法setname()和getname()接收。可手动输入也可使编译器自行生成。
class Person{
//普通成员变量
private String name;
public int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class TestDemo {
public static void main(String[] args) {
Person person = new Person();
person.setName("phf");
System.out.println(person.getName());
}
}
自动生成:
构造方法
1、一个对象实例化产生的步骤有哪些?
①为对象分配内存
②调用合适的构造方法
2、构造方法的语法特点
①方法名与类名相同
②构造方法没有返回值类型声明
③每一个类中一定至少存在一个构造方法(没有明确定义,则系统自动生成一个无参构造)
4.系统会默认生成一个没有的参数的构造方法:
class Person{
//普通成员变量
private String name;
public int age;
//定义一个构造方法
public Person(){
System.out.println("Person()::不带参数的构造方法");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person1 = new Person();
}
}
当我们在类中自行定义无参构造函数时,实例化对象时候会优先调用类中自行定义的构造方法。
此时,代码运行结果为打印:Person()::不带参数的构造方法
当我们没有在类中定义构造方法时,编译器会在类中生成默认构造方法并调用:
5.定义一个带有一个默认参数的构造方法
class Person{
//普通成员变量
private String name;
public int age;
//定义一个构造方法
public Person(String name){
System.out.println("Person(String name)::带一个参数类型的构造方法");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person2 = new Person("bit");
}
}
此时代码打印结果为:Person(String name)::带一个参数类型的构造方法
6.定义一个带有两参数的构造方法
class Person{
//普通成员变量
private String name;
public int age;
//定义一个构造方法
public Person(String name,int age){
this.name = name;
this.age = age;
System.out.println("Person(String name,int age)::带两个参数类型的构造方法");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person3 = new Person("bit",19);
}
}
此时代码打印结果为:Person(String name,int age)::带两个参数类型的构造方法
总结:
1.如果没有实现任何构造方法,那编译器会默认生成一个不带参数的构造方法。一个类中至少有一个构造方法。
2.如果当前类中有其他类型的构造方法,那编译器不会默认生成不带参数的构造方法。
3.构造方法之间可以构成重载。
this和super有什么区别
1、this.data 表示调用当前对象的属性。
2、this.func() 表示调用当前对象的方法。
3、this() 表示调用当前对象的其他构造方法。
举例:
class Person{
//普通成员变量
private String name;
public int age;
public Person(){
this("phf");
System.out.println("Person()::不带参数的构造方法");
}
public Person(String name){
this.name = name;
System.out.println("Person(String name)::带一个参数类型的构造方法");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person = new Person();
}
}
无参构造方法中this()表示调用对象中其他的构造方法,即又调用了带有一个参数的构造方法。结果为:
Person()::不带参数的构造方法 Person(String name)::带一个参数的构造方法
特殊情况:
1. this()只能放到第一行,有且只要一个,所以此时只能选择留下一个。
2.this()只能放在构造方法中,而不能放在成员方法中。
代码块
认识代码块
代码块分为:本地代码块,实例代码块,静态代码块,同步代码块
1.本地代码块
在方法里,写在大括号里的代码
public class TestDemo {
public static void main(String[] args) {
{
//定义在此大括号内的为本地代码块
}
}
}
2.实例代码块
在类中的,写在大括号里的代码
class Person{
//普通成员变量
private String name;
public int age;
{
System.out.println("实例代码块");
}
}
3.静态代码块
在类中,写在大括号了里且被private属性修饰
class Person{
//普通成员变量
private String name;
public int age;
private {
System.out.println("实例代码块");
}
}
代码块如何被调用?
1.在构造方法前被调用,且有固定的顺序。无论静态代码块放到类中的什么位置,都是最先被调用的,其次是实例代码块,最后是构造方法。
class Person{
//普通成员变量
private String name;
public int age;
{
System.out.println("实例代码块");
}
static {
System.out.println("静态代码块");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person = new Person();
}
}
2.静态代码块值被执行一次,不可多次执行,与实例化对象的数量无关。
class Person{
//普通成员变量
private String name;
public int age;
{
System.out.println("实例代码块");
}
static {
System.out.println("静态代码块");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person = new Person();
System.out.println("==========================");
Person person2 = new Person();
}
}
此时代码的结果为:
3.静态代码块不用实例化对象也能被执行,且只能执行一次。
class Person{
//普通成员变量
private String name;
public int age;
{
System.out.println("实例代码块");
}
static {
System.out.println("静态代码块");
}
}
public class TestDemo {
public static void main(String[] args) {
System.out.println(Person.count);
System.out.println(Person.count);
}
}
此时代码打印结果为:
4.都静态的情况下,静态成员变量的值看其定义的顺序。
class Person1{
//定义普通成员变量
public String name;
public int age;
//定义静态成员变量
static public int count = 10;
//静态代码块
static {
count = 99;
System.out.println("静态代码块");
}
}
public class Test {
public static void main(String[] args) {
System.out.println(Person1.count);
}
}
此时count的最终值为99.



