
- 面向对象和面向过程都是解决问题的思维方式,都是代码组织的方式。
- 解决简单问题使用面向过程。
- 解决复杂问题,在宏观上使用面向对象,微观上任然是面向过程。
- 面向对象三大特性:封装、继承、多态。
- 面向过程只有一个封装功能。
- 对象是一种数据结构(对数据的管理模式),将数据和数据行为放到一起。
- 类可以看做是一个模版,或者图纸,系统根据类的定义来造出对象。类就是对象的抽象。
- .对象是具体的事物;类是对对象的抽象;
- 类可以看成一类对象的模板,对象可以看成该类的一个具体实例。
- 类是用于描述同一类型的对象的一个抽象概念,类中定义了这一类对象所应具有的共同的属性、方法。
简单的学生类:
public class Student{
//属性(成员变量)
int id;//学号
String name;//姓名
int age;//年龄
void study(){
System.out.println("我喜欢学习!");
}
//空参构造器,构造方法
Student(){
}
}
一个典型的类
class Computer { String brand; //品牌 } public class SxtStu { //属性 field int id; String sname; int age; Computer comp; //方法 void study() { System.out.println("我正在学习!使用我们的电脑,"+comp.brand); } //构造器 SxtStu() { } public static void main(String[] args) { SxtStu stu1 = new SxtStu(); stu1.sname = "张三"; Computer comp1 = new Computer(); comp1.brand = "联想"; stu1.comp = comp1; stu1.study(); } }对应的UML图
属性(成员变量)的默认值
| 数据类型 | 默认值 |
|---|---|
| 整型 | 0 |
| 浮点型 | 0.0 |
| 字符型 | ‘\u0000’ |
| 布尔型 | false |
| 所有引用类型 | null |
Java虚拟机的内存可以分为三个区域:栈(stack)、堆(heap)、方法区(method area)
-
栈的特点:
- 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈。
- JVM为每一个线程都创建一个栈,用于存放线程执行方法的信息。
- 栈属于线程私有,不能共享。
- 特性:先进后出,后进先出。
- 栈由系统自动分配,连续的内存空间。
-
堆的特点:
- 堆用于存储创建好的对象和数组。
- JVM只有一个堆,所有线程共享。
- 堆是不连续的内存空间,分配灵活,速度慢。
-
方法区(静态区)的特点:
- JVM只有一个方法区,所有线程共享。
- 方法去实际上也是堆,用于存储类、常量相关信息。
- 用来存放程序中永远不变或者唯一的内容。
-
声明格式
[修饰符] 类名(形参列表){ //n条语句 } -
要点
- 通过new关键字调用。
- 构造器虽然有返回值,但是不能定义返回值类型,不能在构造器里面使用return返回值。
- 如果没有定义构造器,则编译器会自动生成一个空参构造器。
- 构造器方法名和类名一致。
-
练习题
- 定义一个“点”(Point)类用来表示二维空间中的点(有两个坐标)。要求如下:
(1) 可以生成具有特定坐标的点对象。
(2) 提供可以设置坐标的方法。
(3)提供可以计算该“点”距另外一点距离的方法。
public class Point{ double x; double y; //构造器 public Point(double x,double y){ this.x=x1; this.y=y1; } //两点距离方法 public double getDistance(Point p){ return Math.sqrt(x-p.x)*(x-p.x)+(y-p.y)*(y-p.y)); } } public class Test{ public static void main(String[] args){ Point p=new Point(3.0,4.0); Point o=new Point(0.0,0.0); System.out.println(p.getDistance(o)); } }
-
内存管理
-
Java的内存管理很大程度指的就是对象的管理,其中包括对象空间的分配和释放。
-
对象空间的分配:使用new关键字创建对象即可
-
对象空间的释放:将对象赋值null即可。垃圾回收器将负责回收所有”不可达”对象的内存空间。
-
-
垃圾回收过程
- 发现无用对象。
- 回收无用对象占用的内存空间。
-
垃圾回收相关算法
-
引用计数法
堆中每个对象都有一个引用计数。被引用一次,计数加1. 被引用变量值变为null,则计数减1,直到计数为0,则表示变成无用对象。优点是算法简单,缺点是“循环引用的无用对象”无法别识别。
-
引用可达法(根搜索算法)
程序把所有的引用关系看作一张图,从一个节点GC ROOT开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完毕之后,剩余的节点则被认为是没有被引用到的节点,即无用的节点。
-
-
堆内存划分
对象分为三种状态:
- 年轻代:新生对象放在Eden区。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象,对应的是Minor GC,每次 Minor GC 会清理年轻代的内存,算法采用效率较高的复制算法,频繁的 *** 作,但是会浪费内存空间。当“年轻代”区域存放满对象后,就将对象存放到年老代区域。
- 年老代:在年轻代中经历了N(默认15)次垃圾回收后仍然存活的对象,就会被放到年老代中。用来存放生命周期较长的对象。年老代对象越来越多,我们就需要启动Major GC和Full GC(全量回收),来一次大扫除,全面清理年轻代区域和年老代区域。
- 持久代:用于存放静态文件,如Java类、方法等。持久代对垃圾回收没有显著影响。
- Minor GC:用于清理年轻代区域。
- Major GC:用于清理老年代区域。
- Full GC:用于清理年轻代、年老代区域。
- 垃圾回收过程
1、新创建的对象,绝大多数都会存储在Eden中,
2、当Eden满了(达到一定比例)不能创建新对象,则触发垃圾回收(GC),将无用对象清理掉,
然后剩余对象复制到某个Survivor中,如S1,同时清空Eden区
3、当Eden区再次满了,会将S1中的不能清空的对象存到另外一个Survivor中,如S2,
同时将Eden区中的不能清空的对象,也复制到S1中,保证Eden和S1,均被清空。
4、重复多次(默认15次)Survivor中没有被清理的对象,则会复制到老年代Old(Tenured)区中,
5、当Old区满了,则会触发一个一次完整地垃圾回收(FullGC),之前新生代的垃圾回收称为(minorGC)
-
JVM调优(Full GC原因)
1.年老代(Tenured)被写满
2.持久代(Perm)被写满
3.System.gc()被显式调用(程序建议GC启动,不是调用GC)
4.上一次GC之后Heap的各域分配策略动态变化
-
开发过程中容易造成的内存泄漏的 *** 作
- 创建大量无用对象
我们在需要大量拼接字符串时,使用了String而不是StringBuilder。
- 静态集合类的使用
像HashMap、Vector、List等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,所有的对象Object也不能被释放。
- 各种连接对象(IO流对象、数据库连接对象、网络连接对象)未关闭
IO流对象、数据库连接对象、网络连接对象等连接对象属于物理连接,和硬盘或者网络连接,不使用的时候一定要关闭。
- 监听器的使用
释放对象时,没有删除相应的监听器。
要点:
- 程序员无权调用垃圾回收器。
2. 程序员可以调用System.gc(),该方法只是通知JVM,并不是运行垃圾回收器。尽量少用,会申请启动Full GC,成本高,影响系统性能。
3. finalize方法,是Java提供给程序员用来释放对象或资源的方法,但是尽量少用。
-
创建对象的过程
- 分配对象空间,并将对象成员变量初始化为0或为空。
- 执行属性值的显示初始化。
- 执行构造方法。
- 返回对象的地址给相关的变量。
** this**:本质上就是用来指代当前对象。
-
this最常用的用法
- 普通方法中,this指向调用该方法的对象;构造方法中,this指向正要初始化的对象。
- 使用this关键字调用重载的构造方法,必须位于构造方法的第一句。
- this不能用于static方法中。
用static声明的成员变量为静态成员变量,也称为类变量。 类变量的生命周期和类相同,在整个应用程序执行期间都有效。
-
特点
- 为该类的公用变量,属于类,被该类的所有实例共享,在类被加载时被显式初始化。
- 对于该类的对象来说,static成员变量只有一份。被该类的所有对象共享。
- 一般使用类名.类属性/方法来调用。
- 在static方法中不可以直接访问非static的成员。
-
核心要点
- static 修饰的成员变量和方法从属于类。
- 普通变量和方法从属于对象。
静态初始化块执行顺序
- 上溯到Object类,先执行Object的静态初始化块,再向下执行子类的静态初始化块,直到我们的类的静态初始化块为止。
- 构造方法执行顺序和上面顺序一样!!
-
基本数据类型参数的传值
传递的是值的副本,不会影响原来的参数。
-
引用数据类型参数的传值
引用类型指的是”对象的地址“。因此在传值的时候副本和原参数都指向同一个地址,改变副本指向的地址值会影响原参数的值。
包机制是Java中管理类的重要手段。 开发中,我们会遇到大量同名的类,通过包我们很容易对解决类重名的问题,也可以实现对类的有效管理。 包对于类,相当于文件夹对于文件的作用。
11、package-
使用package两个要点:
- 通常是类的第一句非注释性语句。
- 包名:域名倒着写,再加上模块名,便于内部管理类。
-
注意事项
- 写项目都要加包,不要使用默认包。
- com.gao和com.gao.car,这两个包没有包含关系,是两个完全独立的包。只是在逻辑上前者是后者的一部分。
-
JDK主要包
Java中常用的包 说明 java.lang 包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能。 java.awt 包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。 java.net 包含执行与网络相关的 *** 作的类。 java.io 包含能提供多种输入/输出功能的类。 java.util 包含一些实用工具类,如定义系统特性、使用与日期日历相关的函数。 注意:
-
Java会默认导入java.lang包下所有的类,因此这些类我们可以直接使用。
-
如果导入两个同名的类,只能用包名+类名来显示调用相关类:
-
-
静态导入
静态导入(static import)是在JDK1.5新增加的功能,其作用是用于导入指定类的静态属性,这样我们可以直接使用静态属性。
package cn.sxt;
//以下两种静态导入的方式二选一即可
import static java.lang.Math.*;//导入Math类的所有静态属性
import static java.lang.Math.PI;//导入Math类的PI属性
public class Test2{
public static void main(String [] args){
System.out.println(PI);
System.out.println(random());
}
}
12、练习题
一、选择题
1.以下语句中关于Java构造方法的说法错误的是(B )。(选择一项)
A.构造方法的作用是为创建对象进行初始化工作,比如给成员变量赋值
B.一个Java类可以没有构造方法,也可以提供1个或多个构造方法
C.构造方法与类同名,不能书写返回值类型
D.构造方法的第一条语句如果是super(),则可以省略,该语句作用是调用父类无参数的构造方法
2.在Java中,以下程序编译运行后的输出结果为(D )。(选择一项)
public class Test {
int x, y;
Test(int x, int y) {
this.x = x;
this.y = y;
}
public static void main(String[] args) {
Test pt1, pt2;
pt1 = new Test(3, 3);
pt2 = new Test(4, 4);
System.out.print(pt1.x + pt2.x);
}
}
A.6
B.34
C.8
D.7
3.在Java中关于静态方法,以下说法中正确的是( AC)。(选择二项)
A.静态方法中不能直接调用非静态方法
B.非静态方法中不能直接调用静态方法
C.静态方法可以用类名直接调用
D.静态方法里可以使用this
4.下列选项中关于Java中类方法的说法错误的是( AC)。(选择二项)
A.在类方法中可用this来调用本类的类方法
B.在类方法中调用本类的类方法时可直接调用
C.在类方法中只能调用本类中的类方法
D.在类方法中调用实例方法需要先创建对象
5.分析如下Java程序的代码所示,则编译运行后的输出结果是(C )。(选择一项)
public class Test {
int count=9;
public void count1(){
count=10;
System.out.print("count1="+count);
}
public void count2(){
System.out.print("count2="+count);
}
public static void main(String[ ] args) {
Test t=new Test();
t.count1();
t.count2();
}
}
A.count1=9; count2=9;
B.count1=10;count2=9;
C.count1=10; count2=10;
D.count1=9; count2=10;
二、简答题
1. 面向过程和面向对象的区别。
答:面向过程是解决问题的步骤;面向对象是吧问题分解成对象进行解决。
2. 类和对象的关系
答:类是对对象的抽象;对象是具体事物。
3. 构造方法的作用和特征
答:作用:用于对象初始化。
特征:
1、用new关键字调用;
2、返回值类型为本类,不能用return返回某个值;
3、没有定义构造器时会自动分配空参构造器;
4、构造器名称与类名一致。
4. this关键字的作用和用法
作用:创建好的对象的地址。
用法:
1、普通方法中,this指向调用该方法的对象;构造方法中,this指向正要初始化的对象。
2、使用this关键字调用重载的构造方法,避免相同的初始化代码。但只能在构造方法中用,并且必须位于构造方法的第一句。
3、this不能用于static方法中。
5. 简述static关键字的作用。
(1). 为该类的公用变量,属于类,被该类的所有实例共享,在类被载入时被显式初始化。
(2). 对于该类的所有对象来说,static成员变量只有一份。被该类的所有对象共享!!
(3). 一般用“类名.类属性/方法”来调用。(也可以通过对象引用或类名(不需要实例化)访问静态成员。)
(4). 在static方法中不可直接访问非static的成员。
三、编码题
1. 编写 Java 程序用于显示人的姓名和年龄。定义一个人类Person。 该类中应该有两个私有属性: 姓名 (name) 和年龄 (age) 。定义构造方法用来初始化数据成员。再定义显示(display()) 方法将姓名和年龄打印出来。在 main 方法中创建人类的实例然后将信息显示。
public class Person {
private String name;
private int age;
public Person(String name,int age) {
// TODO Auto-generated constructor stub
this.name=name;
this.age=age;
}
void display(Person p) {
System.out.printf("name=%s,age=%d",this.name, this.age);
}
public static void main(String[] args) {
Person p=new Person("张三",19);
p.display(p);
}
}
2. 定义一个圆类——Circle,在类的内部提供一个属性:半径®,同时 提供 两个 方 法 : 计算 面积 ( getArea() ) 和 计算 周长(getPerimeter()) 。 通过两个方法计算圆的周长和面积并且对计算结果进行输出。最后定义一个测试类对 Circle 类进行使用。
import java.util.Scanner;
public class Circle {
double r;
Circle(){}
double getArea() {
double area=Math.PI*r*r;
return area;
}
double getPerimeter() {
double perimeter=Math.PI*r*2;
return perimeter;
}
}
//---------------------
import java.util.Scanner;
class Test10 {
public static void main(String[] args) {
Circle c=new Circle();
Scanner sc=new Scanner(System.in);
System.out.println("请输入圆的半径:");
c.r=sc.nextDouble();
double area=c.getArea();
double perimeter=c.getPerimeter();
System.out.println("圆的面积为:"+area);
System.out.println("圆的周长为:"+perimeter);
}
}
3. 构造方法与重载:定义一个网络用户类,信息有用户 ID、用户密码、 email 地址。在建立类的实例时把以上三个信息都作为构造函数的参数输入, 其中用户 ID 和用户密码时必须缺省时 email地址是用户 ID 加上字符串"@gameschool.com"。
public class WebUser {
private int id;
private String pwd;
private String email;
public WebUser(int id, String pwd, String email) {
super();
this.id = id;
this.pwd = pwd;
this.email = email;
}
public WebUser(int id, String pwd) {
super();
this.id = id;
this.pwd = pwd;
email=this.id+"@gameschool.com";
}
@Override
public String toString() {
return "WebUser [id=" + id + ", pwd=" + pwd + ", email=" + email + "]";
}
}
//---------------------------
public class TestWU {
public static void main(String[] args) {
WebUser wu=new WebUser(101,"123");
WebUser wu1=new WebUser(102,"123456","326262222@qq.com");
System.out.println(wu.toString());
System.out.println(wu1.toString());
}
}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)