itext修改pdf文字
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
POM文件
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.1</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.21</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
如何使用
原pdf
结果
字符替换
//输入文件
String source = "G:/问题文件/测试.pdf";
//输出文件
String target = "G:/问题文件/test222.pdf";
//字符串替换,注意设置maxDistance的值,maxDistance太小将无法正常替换文字
ITextPdfUtil.stringReplace(source, target, "颜色 ",30,"*****");
关键字后文字替换
//输入文件
String source = "G:/问题文件/测试.pdf";
//输出文件
String target = "G:/问题文件/test222.pdf";
//关键字之后替换,仅仅支持关键字之后的100范围内的文字覆盖,超出范围将覆盖不到
ITextPdfUtil.afterKeyReplace(source, target, "签字",50,"*****");
工具类
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;
import java.util.List;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.TextRenderInfo;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import javax.imageio.ImageIO;
import static com.itextpdf.text.pdf.PdfWriter.getInstance;
public class ITextPdfUtil {
/**
* @Description : 字符串替换
* @Author : mabo
* maxDistance 字符之间最大距离
*/
public static boolean stringReplace(String source, String target, String keyword,float maxDistance,String replace) throws Exception{
boolean success =false;
List<String> keywords = new ArrayList<>();
keywords.add(keyword);
success = manipulatePdf(source, target, keywords, replace);
if (!success){
success = compareText(source, target, keyword, maxDistance, replace);
}
return success;
}
/**
* @Description : 关键字替换
* @Author : mabo
* maxDistance 字符之间最大距离
*/
public static boolean afterKeyReplace(String source, String target, String keyword,float maxDistance,String replace) throws Exception{
boolean success =false;
List<String> keywords = new ArrayList<>();
keywords.add(keyword);
success = manipulatePdfAfterKey(source, target, keywords, replace);
if (!success){
success = compareTextAfterKey(source, target, keyword, maxDistance, replace);
}
return success;
}
/**
* @Author mabo
* @Description
* 由于部分pdf文字会被分割
* 采用如下文字分割方式,寻找距离最近的字符再进行匹配
*/
public static boolean compareText(String src, String dest, String keyword,float maxDistance,String replace) throws Exception {
boolean success=false;
PdfReader pdfReader = null;
PdfStamper stamper = null;
try {
pdfReader = new PdfReader(src);
stamper = new PdfStamper(pdfReader, new FileOutputStream(dest));
char[] chars = keyword.toCharArray();
HashMap<String, List<PdfBDO>> textMap = new HashMap<>();
for (char c: chars) {
String s = String.valueOf(c);
List<PdfBDO> textLineModes = renderText(pdfReader, s);
textMap.put(s,textLineModes);
}
List<PdfBDO> textLineModes = textMap.get(String.valueOf(chars[0]));
Map<Float,Float> mapY = new HashMap<>();
for (PdfBDO textLineMode: textLineModes) {
//根据首字符 找出同一行的文字
float y = textLineMode.getY();
float x = textLineMode.getX();
mapY.put(y,x);
}
Set<Float> floats = mapY.keySet();
Iterator<Float> iterator = floats.iterator();
HashMap<Float, Map<String,PdfBDO>> keyYMap = new HashMap<>();
while (iterator.hasNext()){
Float y = iterator.next();
Float x = mapY.get(y);
HashMap<String, PdfBDO> tMap = new HashMap<>();
for (int i = 0; i < chars.length; i++) {
char c=chars[i];
List<PdfBDO> textLineModes1 = textMap.get(String.valueOf(c));
for (PdfBDO t : textLineModes1) {
if (t.getY()==y){
//判断两文字之间的具体是否符合要求
float x1 = t.getX();
float absoluteValue = getAbsoluteValue(x1, x);
if (absoluteValue<maxDistance){
Object o = tMap.get(String.valueOf(c));
if (o!=null){
PdfBDO o1 = (PdfBDO) o;
if (getAbsoluteValue(o1.getX(),x)>absoluteValue){
tMap.put(String.valueOf(c),t);
}
}
else {
tMap.put(String.valueOf(c),t);
}
}
}
}
}
keyYMap.put(y,tMap);
}
Set<Float> keySet = keyYMap.keySet();
Iterator<Float> iterator1 = keySet.iterator();
while (iterator1.hasNext()){
Float next = iterator1.next();
Map<String,PdfBDO> map = keyYMap.get(next);
if (map.size()==chars.length){
PdfBDO t = map.get(String.valueOf(chars[0]));
PdfBDO endPdfBDO = map.get(String.valueOf(chars[chars.length - 1]));
float x = t.getX();
float y = t.getY();
float width = endPdfBDO.getX() - x + t.getWidth();
float height = t.getHeight();
int curPage = t.getCurPage();
PdfContentByte canvas = stamper.getOverContent(curPage);
canvas.saveState();
canvas.setColorFill(BaseColor.WHITE);
// 以左下点为原点,x轴的值,y轴的值,总宽度,总高度:
//开始覆盖内容,实际操作位置
canvas.rectangle(x, y, width, height*1.3);
canvas.fill();
canvas.setColorFill(BaseColor.BLACK);
//开始写入文本
canvas.beginText();
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
Font font = new Font(bf,height,Font.BOLD);
//设置字体和大小
canvas.setFontAndSize(font.getBaseFont(), height);
//设置字体的输出位置
canvas.setTextMatrix(x, y+3);
//要输出的text
canvas.showText(replace) ;
canvas.endText();
canvas.fill();
canvas.restoreState();
success=true;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stamper != null)
stamper.close();
if (pdfReader != null)
pdfReader.close();
}
return success;
}
/**
* @Description : 功能说明
* 由于部分pdf文字会被分割
* 采用如下文字分割方式,寻找距离最近的字符再进行匹配
* 匹配后对该字符串后面的文字进行脱敏
*/
public static boolean compareTextAfterKey(String src, String dest, String keyword,float maxDistance,String replace) throws Exception {
boolean success=false;
PdfReader pdfReader = null;
PdfStamper stamper = null;
try {
pdfReader = new PdfReader(src);
stamper = new PdfStamper(pdfReader, new FileOutputStream(dest));
char[] chars = keyword.toCharArray();
HashMap<String, List<PdfBDO>> textMap = new HashMap<>();
for (char c: chars) {
String s = String.valueOf(c);
List<PdfBDO> textLineModes = renderText(pdfReader, s);
textMap.put(s,textLineModes);
}
List<PdfBDO> textLineModes = textMap.get(String.valueOf(chars[0]));
Map<Float,Float> mapY = new HashMap<>();
for (PdfBDO textLineMode: textLineModes) {
//根据首字符 找出同一行的文字
float y = textLineMode.getY();
float x = textLineMode.getX();
mapY.put(y,x);
}
Set<Float> floats = mapY.keySet();
Iterator<Float> iterator = floats.iterator();
HashMap<Float, Map<String,PdfBDO>> keyYMap = new HashMap<>();
while (iterator.hasNext()){
Float y = iterator.next();
Float x = mapY.get(y);
HashMap<String, PdfBDO> tMap = new HashMap<>();
for (int i = 0; i < chars.length; i++) {
char c=chars[i];
List<PdfBDO> textLineModes1 = textMap.get(String.valueOf(c));
for (PdfBDO t : textLineModes1) {
if (t.getY()==y){
//判断两文字之间的具体是否符合要求
float x1 = t.getX();
float absoluteValue = getAbsoluteValue(x1, x);
if (absoluteValue<maxDistance){
Object o = tMap.get(String.valueOf(c));
if (o!=null){
PdfBDO o1 = (PdfBDO) o;
if (getAbsoluteValue(o1.getX(),x)>absoluteValue){
tMap.put(String.valueOf(c),t);
}
}
else {
tMap.put(String.valueOf(c),t);
}
}
}
}
}
keyYMap.put(y,tMap);
}
Set<Float> keySet = keyYMap.keySet();
Iterator<Float> iterator1 = keySet.iterator();
while (iterator1.hasNext()){
Float next = iterator1.next();
Map<String,PdfBDO> map = keyYMap.get(next);
if (map.size()==chars.length){
PdfBDO t = map.get(String.valueOf(chars[chars.length-1]));
float x = t.getX();
float y = t.getY();
float width = t.getWidth();
float height = t.getHeight();
int curPage = t.getCurPage();
PdfContentByte canvas = stamper.getOverContent(curPage);
canvas.saveState();
canvas.setColorFill(BaseColor.WHITE);
// 以左下点为原点,x轴的值,y轴的值,总宽度,总高度:
//开始覆盖内容,实际操作位置
canvas.rectangle(x+width, y, 100, height*1.3);
canvas.fill();
canvas.setColorFill(BaseColor.BLACK);
//开始写入文本
canvas.beginText();
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
Font font = new Font(bf,height,Font.BOLD);
//设置字体和大小
canvas.setFontAndSize(font.getBaseFont(), height);
//设置字体的输出位置
canvas.setTextMatrix(x+width, y+3);
//要输出的text
canvas.showText(replace) ;
canvas.endText();
canvas.fill();
canvas.restoreState();
success=true;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stamper != null)
stamper.close();
if (pdfReader != null)
pdfReader.close();
}
return success;
}
/**
* 根据关键字,在其后进行脱敏
* @Author : mabo
*/
public static boolean manipulatePdfAfterKey(String src, String dest, List<String> keywords,String replace ) throws Exception {
boolean success=false;
PdfReader pdfReader = null;
PdfStamper stamper = null;
try {
pdfReader = new PdfReader(src);
List<PdfBDO> list = renderText(pdfReader, keywords);
stamper = new PdfStamper(pdfReader, new FileOutputStream(dest));
if (list != null) {
for (int i = 0; i < list.size(); i++) {
PdfBDO mode = list.get(i);
PdfContentByte canvas = stamper.getOverContent(mode.getCurPage());
canvas.saveState();
canvas.setColorFill(BaseColor.WHITE);
// 以左下点为原点,x轴的值,y轴的值,总宽度,总高度:
//开始覆盖内容,实际操作位置
canvas.rectangle(mode.getX()+ mode.getWidth(), mode.getY(), 100, mode.getHeight()*1.3);
canvas.fill();
canvas.setColorFill(BaseColor.BLACK);
//开始写入文本
canvas.beginText();
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
Font font = new Font(bf,mode.getHeight(),Font.BOLD);
//设置字体和大小
canvas.setFontAndSize(font.getBaseFont(), mode.getHeight());
//设置字体的输出位置
canvas.setTextMatrix(mode.getX()+mode.getWidth()+10, mode.getY()+3);
//要输出的text
canvas.showText(replace) ;
canvas.endText();
canvas.fill();
canvas.restoreState();
success=true;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stamper != null)
stamper.close();
if (pdfReader != null)
pdfReader.close();
}
return success;
}
/**
* @Description : 匹配pdf中的文字,进行替换
* @Author : mabo
*/
public static boolean manipulatePdf(String src, String dest, List<String> keywords,String replace ) throws Exception {
boolean success=false;
PdfReader pdfReader = null;
PdfStamper stamper = null;
try {
pdfReader = new PdfReader(src);
List<PdfBDO> list = renderText(pdfReader, keywords);
stamper = new PdfStamper(pdfReader, new FileOutputStream(dest));
if (list != null) {
for (int i = 0; i < list.size(); i++) {
PdfBDO mode = list.get(i);
PdfContentByte canvas = stamper.getOverContent(mode.getCurPage());
canvas.saveState();
canvas.setColorFill(BaseColor.WHITE);
// 以左下点为原点,x轴的值,y轴的值,总宽度,总高度:
// canvas.rectangle(mode.getX() - 1, mode.getY(),
// mode.getWidth() + 2, mode.getHeight());
//开始覆盖内容,实际操作位置
canvas.rectangle(mode.getX(), mode.getY(), mode.getWidth(), mode.getHeight()*1.3);
canvas.fill();
canvas.setColorFill(BaseColor.BLACK);
//开始写入文本
canvas.beginText();
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
Font font = new Font(bf,mode.getHeight(),Font.BOLD);
//设置字体和大小
canvas.setFontAndSize(font.getBaseFont(), mode.getHeight());
//设置字体的输出位置
canvas.setTextMatrix(mode.getX(), mode.getY()+3);
//要输出的text
canvas.showText(replace) ;
canvas.endText();
canvas.fill();
canvas.restoreState();
success=true;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stamper != null)
stamper.close();
if (pdfReader != null)
pdfReader.close();
}
return success;
}
public static List<PdfBDO> renderText(PdfReader pdfReader, final List<String> keywords) {
final List<PdfBDO> list = new ArrayList<PdfBDO>();
try {
PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(pdfReader);
int pageNum = pdfReader.getNumberOfPages();
for (int i = 1; i <= pageNum; i++) {
final int curPage = i;
pdfReaderContentParser.processContent(curPage, new RenderListener() {
public void renderText(TextRenderInfo textRenderInfo) {
String text = textRenderInfo.getText();
System.out.println(text);
if (text != null) {
for (int j = 0; j < keywords.size(); j++) {
String keyword = keywords.get(j);
if (text.contains(keyword)) {
com.itextpdf.awt.geom.Rectangle2D.Float bound = textRenderInfo.getBaseline()
.getBoundingRectange();
PdfBDO lineMode = new PdfBDO();
lineMode.setHeight(bound.height == 0 ? PdfBDO.defaultHeight : bound.height);
lineMode.setWidth(bound.width);
lineMode.setX(bound.x);
lineMode.setY(bound.y - PdfBDO.fixHeight);
lineMode.setCurPage(curPage);
list.add(lineMode);
}
}
}
}
public void renderImage(ImageRenderInfo arg0) {
}
public void endTextBlock() {
}
public void beginTextBlock() {
}
});
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
public static List<PdfBDO> renderText(PdfReader pdfReader, String keyword) {
final List<PdfBDO> list = new ArrayList<PdfBDO>();
try {
PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(pdfReader);
int pageNum = pdfReader.getNumberOfPages();
for (int i = 1; i <= pageNum; i++) {
final int curPage = i;
pdfReaderContentParser.processContent(curPage, new RenderListener() {
public void renderText(TextRenderInfo textRenderInfo) {
String text = textRenderInfo.getText();
if (text != null) {
if (text.contains(keyword)) {
com.itextpdf.awt.geom.Rectangle2D.Float bound = textRenderInfo.getBaseline()
.getBoundingRectange();
PdfBDO lineMode = new PdfBDO();
lineMode.setHeight(bound.height == 0 ? PdfBDO.defaultHeight : bound.height);
lineMode.setWidth(bound.width);
lineMode.setX(bound.x);
lineMode.setY(bound.y - PdfBDO.fixHeight);
lineMode.setCurPage(curPage);
list.add(lineMode);
}
}
}
public void renderImage(ImageRenderInfo arg0) {
}
public void endTextBlock() {
}
public void beginTextBlock() {
}
});
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
public static float getAbsoluteValue(float f1, float f2){
if (f1>f2){
return f1-f2;
}else {
return f2-f1;
}
}
public static File outputStream2File (ByteArrayOutputStream out, File file ) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream(file.getName());
fileOutputStream.write(out.toByteArray());
return file;
}
public File inputStream2File (InputStream in ,File file ) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
int ch = 0;
while ((ch = in.read()) != -1) {
out.write(ch);
}
outputStream2File(out,file);
return file;
}
public static InputStream File2InputStream (File file ) throws IOException {
InputStream inputStream = new FileInputStream(file);
return inputStream;
}
/**
*
* @param destPath 生成pdf文件的路劲
* @param images 需要转换的图片路径的数组
* imagesToPdf("G:/test333.pdf",new String[]{"G:/test.jpg"});
* @throws IOException
* @throws DocumentException
*/
public static void imagesToPdf(String destPath, String[] images)
throws IOException, DocumentException {
// 第一步:创建一个document对象。
Document document = new Document();
document.setMargins(0, 0, 0, 0);
// 第二步:
// 创建一个PdfWriter实例,
getInstance(document,new FileOutputStream(destPath));
// 第三步:打开文档。
document.open();
// 第四步:在文档中增加图片。
int len = images.length;
for (int i = 0; i < len; i++) {
Image img = Image.getInstance(images[i]);
img.setAlignment(Image.ALIGN_CENTER);
//根据图片大小设置页面,一定要先设置页面,再newPage(),否则无效
document.setPageSize(new Rectangle(img.getWidth(), img.getHeight()));
document.newPage();
document.add(img);
}
// 第五步:关闭文档。
document.close();
}
/**
* 将PDF文件转换成多张图片
*
* @param pdfFile PDF源文件
* @return 图片字节数组列表
*/
public static void pdf2images(File pdfFile) throws Exception {
String name = pdfFile.getName();
String[] split = name.split("\\.");
//加载PDF
PDDocument pdDocument = PDDocument.load(pdfFile);
//创建PDF渲染器
PDFRenderer renderer = new PDFRenderer(pdDocument);
int pages = pdDocument.getNumberOfPages();
for (int i = 0; i < pages; i++) {
ByteArrayOutputStream output = new ByteArrayOutputStream();
//将PDF的每一页渲染成一张图片
BufferedImage image = renderer.renderImage(i);
ImageIO.write(image, "png", output);
FileOutputStream fileOutputStream = new FileOutputStream("G:/"+split[0]+i+".png");
fileOutputStream.write(output.toByteArray());
fileOutputStream.flush();;
fileOutputStream.close();
}
pdDocument.close();
}
}
实体
public class PdfBDO {
public static final float defaultHeight = 14;
public static final float fixHeight = 4;
private int curPage = 1;
private float height = 0;
private float width = 0;
private float x = 0;
private float y = 0;
public int getCurPage() {
return curPage;
}
public void setCurPage(int curPage) {
this.curPage = curPage;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public float getWidth() {
return width;
}
public void setWidth(float width) {
this.width = width;
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
}
总结
如何使pdf图片,可以结合OCR识别为pdf文字,再使用改工具类即可。
JAVA 基础知识点
什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?
Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。
Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java虚拟机让这个变成可能,因为它知道底层硬件平台的指令长度和其它特性。
什么是J2EE?JVM?JRE?JDK?
(1)J2EE:是为开发企业环境下的应用程序提供的一套解决方案,该技术体系中包含的技术如Servlet、Jsp等,主要针对Web应用程序开发。
(2)JVM:JVM是java虚拟机(JVM Java Virtual Machine),java程序需要运行在虚拟机上,不同平台有自己的虚拟机,因此java语言可以跨平台。
(3)JRE:包括Java虚拟机(JVM Java Virtual Machine)和Java程序所需的核心类库等如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。JRE:JVM+类库。
(4)JDK:JDK是提供给Java开发人员使用的,其中包含了java的开发工具,也包括了JRE。所以安装了JDK,就不用在单独安装JRE了。其中的开发工具:编译工具(javac.exe) 打包工具(jar.exe)等。JDK:JRE+JAVA的开发工具。
static关键字是什么意思?Java中是否可以覆盖(override)一个private或者是static方法?
“static”关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例变量的情况下被访问。
Java中static方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而static方法是编译时静态绑定的。static方法跟类的任何实例都不相关,所以概念上不适用。
Java中也不可以覆盖private方法,因为private修饰的变量和方法只能在当前类中使用,如果是其它类继承当前类,是不能访问到private变量或方法的,当然也不能覆盖。
是否可以在static环境中访问非static变量?
static变量在Java中是属于类的,它在所有的实例中的值是一样的,当类被Java虚拟机载入的时候,会对static变量进行初始化。如果你的代码尝试不用实例来访问非static的变量,编译器会报错,因为这些变量还没有被创建出来,还没有跟任何实例关联上。
Java支持的数据类型有哪些?什么是自动拆装箱?
Java语言支持的8种基本数据类型是:
boolean
byte、char
short、int
long、float、double
自动装箱是Java编译器在基本数据类型和对应的对象包装类型之间做的一个转化。比如:把int转化成integer,double转化成Double,等等。反之就是自动拆箱。
面向对象的三大特性(继承、封装、多态)
继承、封装、多态
什么是继承?
①继承是面向对象程序设计能够提高软件开发效率的重要原因之一。
②继承是具有传递性的,就像现实中孙子不仅长得像爸爸而且还像他爷爷。
③继承来的属性和方法是隐式的,也就是在本类里面是看不见的。
④一个类只能有一个父类,也就是类只能是单继承。
⑤一个接口可以有多个父类,也就是接口可以是多继承。
实际项目开发中,一个类继承于另一个类,那么前者就是后者的子类,反则反之。
什么是封装?
对象数据和操作该对象的指令都是对象自身的一部分,能够实现尽可能对外部隐藏数据。
实际项目开发中,使用封装最多的就是实体类,常常和JavaBean(类必须是具体的和公共的,并且具有无参数的构造器)一起使用。
那么,实体类有那些东西呢?
答:私有的成员变量、无参数的构造器、有参数的构造器、setter和getters方法、重写tostring方法、重写hashCode和equals方法。
什么是多态?
①多态就是对象拥有多种形态:引用多态和方法多态。
②引用多态:父类的引用可以指向本类对象、父类的引用可以指向子类的对象。
③方法多态:创建本类对象时,调用的方法为本类的方法;创建子类对象时,调用的方法为子类重写的方法或者继承的方法。
④存在多态的必要条件:继承、重写。
⑤多态的作用是消除类型之间的耦合关系。
在实际项目开发中,A类继承B类,如果在A类中不重写B类的方法的时候,输出的仍旧是B类方法里面的信息(B b=new A());如果在A类中重写B类的方法的时候,输出的是A类方法里面的信息(B b=new A())。
java为什么不支持多继承?
1.若子类继承的父类中拥有相同的成员变量,子类在引用该变量时将无法判别使用哪个父类的成员变量。
2.若一个子类继承的多个父类拥有相同方法,同时子类并未覆盖该方法(若覆盖,则直接使用子类中该方法),那么调用该方法时将无法确定调用哪个父类的方法。
Java 中覆盖和重载是什么意思?
解析:覆盖和重载是比较重要的基础知识点,并且容易混淆,所以面试中常见。
答:覆盖(Overide)是指子类对父类方法的一种重写,只能比父类抛出更少的异常,访问权限不能比父类的小。
被覆盖的方法不能是 private 的,否则只是在子类中重新定义了一个方法;
重载(Overload)表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同。
面试官: 那么构成重载的条件有哪些?
答:参数类型不同、参数个数不同、参数顺序不同。
面试官: 函数的返回值不同可以构成重载吗?为什么?
答:不可以,因为 Java 中调用函数并不需要强制赋值。举例如下:
如下两个方法:
void f(){}
int f(){ return 1;}
1
2
只要编译器可以根据语境明确判断出语义,比如在 int x = f();中,那么的确可以据此区分重载方法。不过, 有时你并不关心方法的返回值,你想要的是方法调用的其他效果 (这常被称为 “为了副作用而调用”),这时你可能会调用方法而忽略其返回值,所以如果像下面的调用:
fun();
此时 Java 如何才能判断调用的是哪一个 f() 呢?别人如何理解这种代码呢?所以,根据方法返回值来区分重载方法是行不通的。
重定向和转发的区别。
1、重定向是两次请求,转发是一次请求,因此转发的速度要快于重定向
2、重定向之后地址栏上的地址会发生变化,变化成第二次请求的地址,转发之后地址栏上的地址不会变化,还是第一次请求的地址
3、转发是服务器行为,重定向是客户端行为。重定向时浏览器上的网址改变 ,转发是浏览器上的网址不变
4、重定向是两次request,转发只有一次请求
5、重定向时的网址可以是任何网址,转发的网址必须是本站点的网址
抽象类和接口的区别有哪些?
答:
抽象类中可以没有抽象方法;接口中的方法必须是抽象方法;
抽象类中可以有普通的成员变量;接口中的变量必须是 static final 类型的,必须被初始化 , 接口中只有常量,没有变量。
抽象类只能单继承,接口可以继承多个父接口;
Java8 中接口中会有 default 方法,即方法可以被实现。
面试官:抽象类和接口如何选择?
答:
如果要创建不带任何方法定义和成员变量的基类,那么就应该选择接口而不是抽象类。
如果知道某个类应该是基类,那么第一个选择的应该是让它成为一个接口,只有在必须要有方法定义和成员变量的时候,才应该选择抽象类。因为抽象类中允许存在一个或多个被具体实现的方法,只要方法没有被全部实现该类就仍是抽象类。