我有一个类,其中的一个成员是using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace UserObjectsLeak
{
public partial class FrmUserObjectsLeak : Form
{
// This is used to keep references of the labels being added dynamically.
static readonly List<Label> Labels = new List<Label>();
public FrmUserObjectsLeak()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
for (var i = 0; i < 11000; i++)
{
var label = new Label()
{
Text = i.ToString(),
Width = 50
};
Labels.Add(label);
try
{
panel1.Controls.Add(label);
}
catch (System.ComponentModel.Win32Exception ex)
{
lblException.Text = ex.ToString();
return;
}
lblControlsCount.Text = (i).ToString();
// Quick and dirty just to show the progress...
Application.DoEvents();
if (i % 500 == 0)
{
// Remove all labels from the panel,
// keep only the reference in the list.
panel1.Controls.Clear();
}
}
}
private void btnClear_Click(object sender, EventArgs e)
{
panel1.Controls.Clear();
Labels.Clear();
lblControlsCount.Text = "";
lblException.Text = "";
}
#region Designer code
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.btnStart = new System.Windows.Forms.Button();
this.lblControlsCount = new System.Windows.Forms.Label();
this.btnClear = new System.Windows.Forms.Button();
this.panel1 = new System.Windows.Forms.FlowLayoutPanel();
this.lblException = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(15, 17);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(191, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Click the button to start adding controls";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(12, 95);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(77, 13);
this.label2.TabIndex = 1;
this.label2.Text = "controls count:";
//
// btnStart
//
this.btnStart.Location = new System.Drawing.Point(12, 49);
this.btnStart.Name = "btnStart";
this.btnStart.Size = new System.Drawing.Size(75, 23);
this.btnStart.TabIndex = 2;
this.btnStart.Text = "Start";
this.btnStart.UseVisualStyleBackColor = true;
this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
//
// lblControlsCount
//
this.lblControlsCount.AutoSize = true;
this.lblControlsCount.Location = new System.Drawing.Point(95, 95);
this.lblControlsCount.Name = "lblControlsCount";
this.lblControlsCount.Size = new System.Drawing.Size(0, 13);
this.lblControlsCount.TabIndex = 3;
//
// btnClear
//
this.btnClear.Location = new System.Drawing.Point(98, 49);
this.btnClear.Name = "btnClear";
this.btnClear.Size = new System.Drawing.Size(75, 23);
this.btnClear.TabIndex = 5;
this.btnClear.Text = "Clear";
this.btnClear.UseVisualStyleBackColor = true;
this.btnClear.Click += new System.EventHandler(this.btnClear_Click);
//
// panel1
//
this.panel1.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
this.panel1.Location = new System.Drawing.Point(226, 17);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(200, 148);
this.panel1.TabIndex = 6;
//
// lblException
//
this.lblException.AutoSize = true;
this.lblException.Location = new System.Drawing.Point(15, 179);
this.lblException.Name = "lblException";
this.lblException.Size = new System.Drawing.Size(0, 13);
this.lblException.TabIndex = 7;
//
// frmUserObjectsLeak
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(452, 308);
this.Controls.Add(this.lblException);
this.Controls.Add(this.panel1);
this.Controls.Add(this.btnClear);
this.Controls.Add(this.lblControlsCount);
this.Controls.Add(this.btnStart);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Name = "FrmUserObjectsLeak";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "User Objects Leak Demo";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button btnStart;
private System.Windows.Forms.Label lblControlsCount;
private System.Windows.Forms.Button btnClear;
private System.Windows.Forms.FlowLayoutPanel panel1;
private System.Windows.Forms.Label lblException;
#endregion Designer code
}
}
,所以我有一个采用相同类型的构造函数,一切都很好。
ArrayList<ArrayList<Double>> elements
但是,我还需要能够使用类型为public elementArray(ArrayList<ArrayList<Double>> elements)
{
this.elements = elements;
// a bunch of other stuff happens
}
的输入进行构造,因此我首先将其转换为2D列表类型,然后调用原始构造函数...
Double[][]
除了在我的构造函数中发生的第一件事外,我无法调用其他构造函数!我是否注定要在此处复制粘贴,或者有什么聪明的方法可以做我想要的事情?
答案 0 :(得分:3)
一种解决方案是将转换提取为静态方法:
public elementArray(Double[][] array) {
this(convert(elements));
}
private static ArrayList<ArrayList<Double>> convert(Double[][] array) {
// convert Double[][] array to ArrayList<ArrayList<Double>> elements
}
答案 1 :(得分:3)
调用this()
之前没有代码,也不能调用其他实例方法。
您可以将该转换提取为单独的静态方法:
private static ArrayList<ArrayList<Double>> arrayToList(Double[][] d) {
//convert and return list
}
并在第二个构造函数中重用此方法:
public elementArray(Double[][] array) {
this(arrayToList(array));
}
答案 2 :(得分:3)
常用的模式是改为使用Builder。
https://iluwatar.github.io/java-design-patterns/patterns/builder/
或静态工厂方法。
https://iluwatar.github.io/java-design-patterns/patterns/factory-method/
例如使用静态工厂方法,您将只有一个(可能是私有的)构造函数,该构造函数接受类所需的最原始版本。
public class elementArray{
public elementArray(ArrayList<ArrayList<Double>> elements)
{
this.elements = elements;
// a bunch of other stuff happens
}
public static elementArray create(Double[][] array)
{
// convert Double[][] array to ArrayList<ArrayList<Double>> elements
return new elementArray(elements);
}
public static elementArray create(ArrayList<ArrayList<Double>> elements)
{
return new elementArray(elements);
}
}
然后,您将调用静态方法,而不是调用构造函数。
elementArray.create(new double[][]{{1.0d},{2.0d}});
在最近的Java中,Guava和Java标准库中已经相当普遍地使用了它。
请参见Arrays.asList
https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList-T...-
答案 3 :(得分:-1)
但是最好使用List而不是ArrayList。
public elementArray(Double[][] array) {
this(convert(elements));
}
static ArrayList<ArrayList<Double>> convert(Double[][] elements) {
return IntStream.range(0, elements.length)
.mapToObj(i -> IntStream.range(0, elements[i].length)
.mapToObj(j -> elements[i][j])
.collect(ArrayList::new, List::add, (u, v) -> u.addAll(v)))
.collect(ArrayList::new,
(u, v) -> v.add(u),
(u, v) -> u.addAll(v));
}